home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / comm / term / term_47a_pch.lha / Source / term-4.7a / Tools.c < prev    next >
C/C++ Source or Header  |  1996-11-02  |  74KB  |  4,119 lines

  1. /*
  2. **    Tools.c
  3. **
  4. **    Miscellaneous support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* Current timer state. */
  17.  
  18. STATIC BOOL TimerRunning;
  19.  
  20.     /* ListViewStateFill(struct LVDrawMsg *Msg):
  21.      *
  22.      *    Draw the ghosting pattern over a ghosted listview line.
  23.      */
  24.  
  25. VOID
  26. ListViewStateFill(struct LVDrawMsg *Msg)
  27. {
  28.     if(Msg->lvdm_State == LVR_SELECTEDDISABLED || Msg->lvdm_State == LVR_NORMALDISABLED)
  29.     {
  30.         struct RastPort    *RPort = Msg->lvdm_RastPort;
  31.         ULONG Ghosting = 0x44441111;
  32.  
  33.         SetABPenDrMd(RPort,Msg->lvdm_DrawInfo->dri_Pens[SHADOWPEN],0,JAM1);
  34.  
  35.         SetAfPt(RPort,(UWORD *)&Ghosting,1);
  36.  
  37.         RectFill(RPort,Msg->lvdm_Bounds.MinX,Msg->lvdm_Bounds.MinY,Msg->lvdm_Bounds.MaxX,Msg->lvdm_Bounds.MaxY);
  38.  
  39.         SetAfPt(RPort,NULL,0);
  40.     }
  41. }
  42.  
  43.     /* EraseWindow(struct Window *Window):
  44.      *
  45.      *    Fills the interior of a window in the background colour.
  46.      */
  47.  
  48. VOID
  49. EraseWindow(struct Window *Window,UWORD *Pens)
  50. {
  51.     LONG Left,Top,Right,Bottom;
  52.  
  53.     Left    = Window->BorderLeft;
  54.     Top        = Window->BorderTop;
  55.     Right    = Window->Width - (Window->BorderRight + 1);
  56.     Bottom    = Window->Height - (Window->BorderBottom + 1);
  57.  
  58.     if(Pens)
  59.     {
  60.         SetPens(RPort,Pens[BACKGROUNDPEN],0,JAM1);
  61.  
  62.         RectFill(Window->RPort,Left,Top,Right,Bottom);
  63.     }
  64.     else
  65.         EraseRect(Window->RPort,Left,Top,Right,Bottom);
  66. }
  67.  
  68.     /* GetListMaxPen(UWORD *Pens):
  69.      *
  70.      *    Calculates the maximum pen number index to be
  71.      *    used for listview text rendering.
  72.      */
  73.  
  74. LONG
  75. GetListMaxPen(UWORD *Pens)
  76. {
  77.     STATIC BYTE PenTable[] =
  78.     {
  79.         TEXTPEN,
  80.         BACKGROUNDPEN,
  81.         FILLTEXTPEN,
  82.         FILLPEN,
  83.         SHADOWPEN,
  84.         HIGHLIGHTTEXTPEN,
  85.     };
  86.  
  87.     LONG Max,Pen,i;
  88.  
  89.     for(i = 0, Max = -1 ; i < NUM_ELEMENTS(PenTable) ; i++)
  90.     {
  91.         Pen = Pens[PenTable[i]];
  92.  
  93.         if(Pen > Max)
  94.             Max = Pen;
  95.     }
  96.  
  97.     return(Max);
  98. }
  99.  
  100.     /* FillBox(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height):
  101.      *
  102.      *    Fill a rectangular area with the current foregroung colour.
  103.      */
  104.  
  105. VOID
  106. FillBox(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height)
  107. {
  108.     if(Width > 0 && Height > 0)
  109.         RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
  110. }
  111.  
  112. VOID
  113. FillWindowBox(struct Window *Window,LONG Left,LONG Top,LONG Width,LONG Height)
  114. {
  115.     if(Left + Width > WindowWidth)
  116.         Width = WindowWidth - Left - 1;
  117.  
  118.     if(Top + Height > WindowHeight)
  119.         Height = WindowHeight - Top - 1;
  120.  
  121.     if(Width > 0 && Height > 0)
  122.     {
  123.         Left    += Window->BorderLeft;
  124.         Top        += Window->BorderTop;
  125.  
  126.         RectFill(Window->RPort,Left,Top,Left + Width - 1,Top + Height - 1);
  127.     }
  128. }
  129.  
  130.     /* PlaceText(struct RastPort *RPort,LONG Left,LONG Top,STRPTR String,LONG Len):
  131.      *
  132.      *    Print some text at a specific position.
  133.      */
  134.  
  135. VOID
  136. PlaceText(struct RastPort *RPort,LONG Left,LONG Top,STRPTR String,LONG Len)
  137. {
  138.     Move(RPort,Left,Top + RPort->TxBaseline);
  139.     Text(RPort,String,Len);
  140. }
  141.  
  142.     /* SetPens(struct RastPort *RPort,ULONG APen,ULONG BPen,ULONG DrMd):
  143.      *
  144.      *    Set rendering attributes.
  145.      */
  146.  
  147. VOID
  148. SetPens(struct RastPort *RPort,ULONG APen,ULONG BPen,ULONG DrMd)
  149. {
  150.     if(Kick30)
  151.         SetABPenDrMd(RPort,APen,BPen,DrMd);
  152.     else
  153.     {
  154.         if(APen != RPort->FgPen)
  155.             SetAPen(RPort,APen);
  156.  
  157.         if(BPen != RPort->BgPen)
  158.             SetBPen(RPort,BPen);
  159.  
  160.         if(DrMd != RPort->DrawMode)
  161.             SetDrMd(RPort,DrMd);
  162.     }
  163. }
  164.  
  165.     /* Atol(STRPTR Buffer):
  166.      *
  167.      *    Convert ASCII representation to long word.
  168.      */
  169.  
  170. LONG
  171. Atol(STRPTR Buffer)
  172. {
  173.     LONG Result;
  174.  
  175.     StrToLong(Buffer,&Result);
  176.  
  177.     return(Result);
  178. }
  179.  
  180.     /* StripSpaces(STRPTR String):
  181.      *
  182.      *    Strip leading and trailing spaces from a string.
  183.      */
  184.  
  185. VOID
  186. StripSpaces(STRPTR String)
  187. {
  188.     if(String)
  189.     {
  190.         STRPTR To;
  191.         LONG Len;
  192.  
  193.         To = String;
  194.  
  195.         while(*String == ' ')
  196.             String++;
  197.  
  198.         if(Len = strlen(String))
  199.         {
  200.             while(Len > 0 && String[Len - 1] == ' ')
  201.                 Len--;
  202.  
  203.             while(Len--)
  204.                 *To++ = *String++;
  205.         }
  206.  
  207.         *To = 0;
  208.     }
  209. }
  210.  
  211.     /* ReplaceWindowInfo(struct WindowInfo *NewInfo):
  212.      *
  213.      *    Drop the window info into the right place.
  214.      */
  215.  
  216. VOID
  217. ReplaceWindowInfo(struct WindowInfo *NewInfo)
  218. {
  219.     LONG i;
  220.  
  221.     ObtainSemaphore(&WindowInfoSemaphore);
  222.  
  223.     for(i = 0 ; WindowInfoTable[i].ID != -1 ; i++)
  224.     {
  225.         if(WindowInfoTable[i].ID == NewInfo->ID)
  226.         {
  227.             CopyMem(NewInfo,&WindowInfoTable[i],sizeof(struct WindowInfo));
  228.  
  229.             break;
  230.         }
  231.     }
  232.  
  233.     ReleaseSemaphore(&WindowInfoSemaphore);
  234. }
  235.  
  236.     /* PutWindowInfo():
  237.      *
  238.      *    Store window size and position relative to
  239.      *    the main window.
  240.      */
  241.  
  242. VOID
  243. PutWindowInfo(LONG ID,LONG Left,LONG Top,LONG Width,LONG Height)
  244. {
  245.     LONG WindowLeft,WindowTop,WindowWidth,WindowHeight;
  246.     struct WindowInfo *Info;
  247.     ULONG IntuiLock;
  248.     LONG i;
  249.  
  250.     ObtainSemaphore(&WindowInfoSemaphore);
  251.  
  252.     for(i = 0 ; WindowInfoTable[i].ID != -1 ; i++)
  253.     {
  254.         if(WindowInfoTable[i].ID == ID)
  255.         {
  256.             Info = &WindowInfoTable[i];
  257.  
  258.             break;
  259.         }
  260.     }
  261.  
  262.     IntuiLock = LockIBase(NULL);
  263.  
  264.     WindowLeft        = Window->LeftEdge;
  265.     WindowTop        = Window->TopEdge;
  266.     WindowWidth        = Window->Width;
  267.     WindowHeight    = Window->Height;
  268.  
  269.     UnlockIBase(IntuiLock);
  270.  
  271.     Info->WindowFlags = NULL;
  272.  
  273.     if(WindowWidth == Width && WindowLeft == Left)
  274.         Info->WindowFlags |= WC_EXPANDWIDTH;
  275.     else
  276.     {
  277.         if(Left == WindowLeft + WindowWidth)
  278.             Info->WindowFlags |= WC_ALIGNSIDE;
  279.  
  280.         if(WindowLeft == Left)
  281.             Info->WindowFlags |= WC_ALIGNLEFT;
  282.  
  283.         if(WindowLeft + WindowWidth == Left + Width)
  284.             Info->WindowFlags |= WC_ALIGNRIGHT;
  285.     }
  286.  
  287.     if(WindowHeight == Height && WindowTop + Window->BorderTop == Top)
  288.         Info->WindowFlags |= WC_EXPANDHEIGHT;
  289.     else
  290.     {
  291.         if(Top == WindowTop + WindowHeight)
  292.             Info->WindowFlags |= WC_ALIGNBELOW;
  293.  
  294.         if(Top == WindowTop + Window->BorderTop)
  295.             Info->WindowFlags |= WC_ALIGNTOP;
  296.  
  297.         if(WindowTop + WindowHeight == Top + Height)
  298.             Info->WindowFlags |= WC_ALIGNBOTTOM;
  299.     }
  300.  
  301.     Info->Left        = Left;
  302.     Info->Top        = Top;
  303.     Info->Width        = Width;
  304.     Info->Height    = Height;
  305.  
  306.     ReleaseSemaphore(&WindowInfoSemaphore);
  307. }
  308.  
  309.     /* GetWindowInfo():
  310.      *
  311.      *    Set the window size and position in relation to
  312.      *    the main window.
  313.      */
  314.  
  315. VOID
  316. GetWindowInfo(LONG ID,LONG *Left,LONG *Top,LONG *Width,LONG *Height,LONG DefWidth,LONG DefHeight)
  317. {
  318.     LONG WindowLeft,WindowTop,WindowWidth,WindowHeight;
  319.     struct WindowInfo *Info;
  320.     ULONG IntuiLock;
  321.     LONG i;
  322.  
  323.     SafeObtainSemaphoreShared(&WindowInfoSemaphore);
  324.  
  325.     Info = NULL;
  326.  
  327.     for(i = 0 ; WindowInfoTable[i].ID != -1 ; i++)
  328.     {
  329.         if(WindowInfoTable[i].ID == ID)
  330.         {
  331.             Info = &WindowInfoTable[i];
  332.  
  333.             break;
  334.         }
  335.     }
  336.  
  337.     if(Info && ID == WINDOW_MAIN)
  338.     {
  339.         *Left    = Info->Left;
  340.         *Top    = Info->Top;
  341.         *Width    = Info->Width;
  342.         *Height    = Info->Height;
  343.     }
  344.     else
  345.     {
  346.         if(Window)
  347.         {
  348.             IntuiLock = LockIBase(NULL);
  349.  
  350.             WindowLeft        = Window->LeftEdge;
  351.             WindowTop        = Window->TopEdge;
  352.             WindowWidth        = Window->Width;
  353.             WindowHeight    = Window->Height;
  354.  
  355.             UnlockIBase(IntuiLock);
  356.  
  357.             if(DefWidth && DefWidth < WindowWidth / 2)
  358.                 DefWidth = WindowWidth / 2;
  359.  
  360.             if(DefHeight && DefHeight < WindowHeight / 2)
  361.                 DefHeight = WindowHeight / 2;
  362.         }
  363.  
  364.         if(*Width)
  365.         {
  366.             if(Info->Width)
  367.                 *Left = Info->Left;
  368.             else
  369.                 *Left = WindowLeft + (WindowWidth - *Width) / 2;
  370.         }
  371.         else
  372.         {
  373.             if(DefWidth && !Info->Width)
  374.             {
  375.                 *Width    = DefWidth;
  376.                 *Left    = WindowLeft + (WindowWidth - *Width) / 2;
  377.             }
  378.             else
  379.             {
  380.                 if(Info->Width)
  381.                 {
  382.                     *Width    = Info->Width;
  383.                     *Left    = Info->Left;
  384.                 }
  385.                 else
  386.                 {
  387.                     *Width    = WindowWidth;
  388.                     *Left    = WindowLeft;
  389.                 }
  390.             }
  391.         }
  392.  
  393.         if(*Height)
  394.         {
  395.             if(Info->Height)
  396.                 *Top = Info->Top;
  397.             else
  398.                 *Top = WindowTop + (WindowHeight - *Height) / 2;
  399.         }
  400.         else
  401.         {
  402.             if(DefHeight && !Info->Height)
  403.             {
  404.                 *Height    = DefHeight;
  405.                 *Top    = WindowTop + (WindowHeight - *Height) / 2;
  406.             }
  407.             else
  408.             {
  409.                 if(Info->Height)
  410.                 {
  411.                     *Height    = Info->Height;
  412.                     *Top    = Info->Top;
  413.                 }
  414.                 else
  415.                 {
  416.                     *Height    = WindowHeight;
  417.                     *Top    = WindowTop;
  418.                 }
  419.             }
  420.         }
  421.  
  422.         if(Info->WindowFlags & WC_ALIGNSIDE)
  423.             *Left = WindowLeft + WindowWidth;
  424.  
  425.         if(Info->WindowFlags & WC_ALIGNBELOW)
  426.             *Top = WindowTop + WindowHeight;
  427.  
  428.         if(Info->WindowFlags & WC_ALIGNLEFT)
  429.             *Left = WindowLeft;
  430.  
  431.         if(Info->WindowFlags & WC_ALIGNTOP)
  432.             *Top = WindowTop;
  433.  
  434.         if(Info->WindowFlags & WC_ALIGNRIGHT)
  435.             *Left = WindowLeft + WindowWidth - *Width;
  436.  
  437.         if(Info->WindowFlags & WC_ALIGNBOTTOM)
  438.             *Top = WindowTop + WindowHeight - *Height;
  439.  
  440.         if(Info->WindowFlags & WC_EXPANDWIDTH)
  441.             *Width = WindowWidth;
  442.  
  443.         if(Info->WindowFlags & WC_EXPANDHEIGHT)
  444.             *Height = WindowHeight;
  445.  
  446.         if(*Top == WindowTop && *Left == WindowLeft)
  447.         {
  448.             LONG TitleHeight = Window->BorderTop;
  449.  
  450.             if(*Height == WindowHeight)
  451.                 *Height -= TitleHeight;
  452.  
  453.             *Top += TitleHeight;
  454.         }
  455.     }
  456.  
  457.     ReleaseSemaphore(&WindowInfoSemaphore);
  458. }
  459.  
  460.     /* GetBitMapDepth(struct BitMap *BitMap):
  461.      *
  462.      *    Return the depth of a BitMap.
  463.      */
  464.  
  465. LONG
  466. GetBitMapDepth(struct BitMap *BitMap)
  467. {
  468.     LONG Depth;
  469.  
  470.     if(Kick30)
  471.         Depth = (LONG)GetBitMapAttr(BitMap,BMA_DEPTH);
  472.     else
  473.         Depth = BitMap->Depth;
  474.  
  475.     if(Depth > 8)
  476.         Depth = 8;
  477.  
  478.     return(Depth);
  479. }
  480.  
  481.     /* GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI):
  482.      *
  483.      *    Get screen DPI resolution values.
  484.      */
  485.  
  486. VOID
  487. GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI)
  488. {
  489.     struct DisplayInfo DisplayInfo;
  490.  
  491.     *X_DPI = *Y_DPI = 72;
  492.  
  493.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode))
  494.     {
  495.         if(DisplayInfo.PixelSpeed && DisplayInfo.Resolution.x && DisplayInfo.Resolution.y)
  496.         {
  497.             *X_DPI = (35 * 140) / DisplayInfo.PixelSpeed;
  498.             *Y_DPI = (*X_DPI * DisplayInfo.Resolution.x) / DisplayInfo.Resolution.y;
  499.         }
  500.     }
  501. }
  502.  
  503.     /* AddProtection(STRPTR FileName,ULONG Mask):
  504.      *
  505.      *    Set bits in the protection mask of a file.
  506.      */
  507.  
  508. VOID
  509. AddProtection(STRPTR Name,ULONG Mask)
  510. {
  511.     BPTR FileLock;
  512.     D_S(struct FileInfoBlock,FileInfo);
  513.  
  514.     if(FileLock = Lock(Name,ACCESS_READ))
  515.     {
  516.         if(Examine(FileLock,FileInfo))
  517.         {
  518.             UnLock(FileLock);
  519.  
  520.             if(Mask == FIBF_EXECUTE)
  521.                 Mask |= FileInfo->fib_Protection & ~(FIBF_OTR_EXECUTE|FIBF_GRP_EXECUTE);
  522.             else
  523.                 Mask |= FileInfo->fib_Protection;
  524.  
  525.             SetProtection(Name,Mask);
  526.         }
  527.         else
  528.             UnLock(FileLock);
  529.     }
  530. }
  531.  
  532.     /* GetPubScreenName(struct Screen *Screen,STRPTR Name):
  533.      *
  534.      *    Get the name of a public screen.
  535.      */
  536.  
  537. BOOL
  538. GetPubScreenName(struct Screen *Screen,STRPTR Name)
  539. {
  540.     struct List                *PubScreenList;
  541.     struct PubScreenNode    *ScreenNode;
  542.     BOOL                     GotIt;
  543.  
  544.     PubScreenList = LockPubScreenList();
  545.  
  546.     for(ScreenNode = (struct PubScreenNode *)PubScreenList->lh_Head, GotIt = FALSE ; !GotIt && ScreenNode->psn_Node.ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode->psn_Node.ln_Succ)
  547.     {
  548.         if(ScreenNode->psn_Screen == Screen)
  549.         {
  550.             strcpy(Name,ScreenNode->psn_Node.ln_Name);
  551.             GotIt = TRUE;
  552.         }
  553.     }
  554.  
  555.     UnlockPubScreenList();
  556.  
  557.     return(GotIt);
  558. }
  559.  
  560.     /* InitSinglePort(struct MsgPort *Port):
  561.      *
  562.      *    Initialize a plain MsgPort (as created on the stack) for
  563.      *    usage. Don't try this at home, kids!
  564.      */
  565.  
  566. VOID
  567. InitSinglePort(struct MsgPort *Port)
  568. {
  569.     memset(Port,0,sizeof(struct MsgPort));
  570.  
  571.     Port->mp_Flags        = PA_SIGNAL;
  572.     Port->mp_SigBit        = SIGB_SINGLE;
  573.     Port->mp_SigTask    = FindTask(NULL);
  574.  
  575.     NewList(&Port->mp_MsgList);
  576. }
  577.  
  578.     /* GoodStream(BPTR Stream):
  579.      *
  580.      *    Check to see whether the current input file
  581.      *    is an interactive stream.
  582.      */
  583.  
  584. BOOL
  585. GoodStream(BPTR Stream)
  586. {
  587.     if(!Stream)
  588.         Stream = Input();
  589.  
  590.     if(Stream)
  591.     {
  592.         struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  593.  
  594.         if(Handle->fh_Type)
  595.         {
  596.             if(IsInteractive(Stream))
  597.                 return(TRUE);
  598.         }
  599.     }
  600.  
  601.     return(FALSE);
  602. }
  603.  
  604.     /* GetProgramIcon():
  605.      *
  606.      *    Try to find the icon of the program.
  607.      */
  608.  
  609. struct DiskObject *
  610. GetProgramIcon()
  611. {
  612.     struct DiskObject *Icon = NULL;
  613.  
  614.         /* Run from Workbench? */
  615.  
  616.     if(WBenchMsg)
  617.     {
  618.             /* Sanity check. */
  619.  
  620.         if(WBenchMsg->sm_ArgList)
  621.         {
  622.                 /* Yet another sanity check. */
  623.  
  624.             if(WBenchMsg->sm_ArgList->wa_Name)
  625.             {
  626.                     /* Try to find the icon in the current directory. */
  627.  
  628.                 if(Icon = GetDiskObjectNew(WBenchMsg->sm_ArgList->wa_Name))
  629.                 {
  630.                     if(Icon->do_Type != WBTOOL)
  631.                     {
  632.                         FreeDiskObject(Icon);
  633.  
  634.                         Icon = NULL;
  635.                     }
  636.                 }
  637.  
  638.                 if(!Icon)
  639.                 {
  640.                     BPTR NewLock;
  641.  
  642.                         /* Move to the directory the
  643.                          * program was run from.
  644.                          */
  645.  
  646.                     if(NewLock = Lock("PROGDIR:",ACCESS_READ))
  647.                     {
  648.                         BPTR OldLock;
  649.  
  650.                         OldLock = CurrentDir(NewLock);
  651.  
  652.                             /* Try to fetch the icon, use the
  653.                              * default name if necessary.
  654.                              */
  655.  
  656.                         if(Icon = GetDiskObjectNew(WBenchMsg->sm_ArgList->wa_Name))
  657.                         {
  658.                             if(Icon->do_Type != WBTOOL)
  659.                             {
  660.                                 FreeDiskObject(Icon);
  661.  
  662.                                 Icon = NULL;
  663.                             }
  664.                         }
  665.  
  666.                         if(!Icon)
  667.                         {
  668.                             if(Icon = GetDiskObjectNew("term"))
  669.                             {
  670.                                 if(Icon->do_Type != WBTOOL)
  671.                                 {
  672.                                     FreeDiskObject(Icon);
  673.  
  674.                                     Icon = NULL;
  675.                                 }
  676.                             }
  677.                         }
  678.  
  679.                         CurrentDir(OldLock);
  680.  
  681.                         UnLock(NewLock);
  682.                     }
  683.                 }
  684.             }
  685.         }
  686.     }
  687.  
  688.         /* Still no success. */
  689.  
  690.     if(!Icon)
  691.     {
  692.             /* Use the default names. */
  693.  
  694.         if(Icon = GetDiskObjectNew("term"))
  695.         {
  696.             if(Icon->do_Type != WBTOOL)
  697.             {
  698.                 FreeDiskObject(Icon);
  699.  
  700.                 Icon = NULL;
  701.             }
  702.         }
  703.  
  704.         if(!Icon)
  705.         {
  706.             if(Icon = GetDiskObjectNew("PROGDIR:term"))
  707.             {
  708.                 if(Icon->do_Type != WBTOOL)
  709.                 {
  710.                     FreeDiskObject(Icon);
  711.  
  712.                     Icon = NULL;
  713.                 }
  714.             }
  715.         }
  716.     }
  717.  
  718.     return(Icon);
  719. }
  720.  
  721.     /* GetPenIndex(LONG Pen):
  722.      *
  723.      *    Get the table index corresponding to an on-screen
  724.      *    text rendering pen.
  725.      */
  726.  
  727. LONG
  728. GetPenIndex(LONG Pen)
  729. {
  730.     LONG i,Result = 0;
  731.  
  732.     for(i = 0 ; i < 16 ; i++)
  733.     {
  734.         if(MappedPens[0][i] == Pen)
  735.         {
  736.             Result = i;
  737.             break;
  738.         }
  739.     }
  740.  
  741.     return(Result);
  742. }
  743.  
  744.     /* GetScreenWidth(struct Window *Window):
  745.      *
  746.      *    Query the current screen width.
  747.      */
  748.  
  749. LONG
  750. GetScreenWidth(struct Window *Window)
  751. {
  752.     if(Window)
  753.     {
  754.         if(Window->Width > ScreenWidth || Window->LeftEdge < -Window->WScreen->LeftEdge || Window->LeftEdge + Window->WScreen->LeftEdge + Window->Width > ScreenWidth)
  755.             return(ScreenWidth);
  756.         else
  757.             return(Window->Width - (Window->BorderLeft + Window->BorderRight));
  758.     }
  759.     else
  760.         return(ScreenWidth);
  761. }
  762.  
  763.     /* GetScreenHeight(struct Window *Window):
  764.      *
  765.      *    Query the current screen height.
  766.      */
  767.  
  768. LONG
  769. GetScreenHeight(struct Window *Window)
  770. {
  771.     if(Window)
  772.     {
  773.         if(Window->Height > ScreenHeight || Window->TopEdge < -Window->WScreen->TopEdge || Window->TopEdge + Window->WScreen->TopEdge + Window->Height > ScreenHeight)
  774.             return(ScreenHeight);
  775.         else
  776.             return(Window->Height - (Window->BorderTop + Window->BorderBottom));
  777.     }
  778.     else
  779.         return(ScreenHeight);
  780. }
  781.  
  782.     /* GetLeft(struct Screen *Screen):
  783.      *
  784.      *    Get the screen left edge.
  785.      */
  786.  
  787. STATIC LONG
  788. GetLeft(struct Screen *Screen)
  789. {
  790.     if(Screen->LeftEdge >= 0)
  791.         return(0);
  792.     else
  793.         return(-Screen->LeftEdge);
  794. }
  795.  
  796.     /* GetScreenLeft(struct Window *Window):
  797.      *
  798.      *    Query the current screen left edge.
  799.      */
  800.  
  801. LONG
  802. GetScreenLeft(struct Window *Window)
  803. {
  804.     if(Window)
  805.     {
  806.         if(Window->Width > ScreenWidth || Window->LeftEdge < -Window->WScreen->LeftEdge || Window->LeftEdge + Window->WScreen->LeftEdge + Window->Width > ScreenWidth)
  807.             return(GetLeft(Window->WScreen));
  808.         else
  809.             return(Window->LeftEdge + Window->BorderLeft);
  810.     }
  811.     else
  812.     {
  813.         struct Screen *PubScreen = LockPubScreen(NULL);
  814.         LONG Result;
  815.  
  816.         Result = GetLeft(PubScreen ? PubScreen : SharedScreen);
  817.  
  818.         UnlockPubScreen(NULL,PubScreen);
  819.  
  820.         return(Result);
  821.     }
  822. }
  823.  
  824.     /* OldGetAPen(struct RastPort *RPort):
  825.      *
  826.      *    Query the current primary rendering colour (old style).
  827.      */
  828.  
  829. ULONG
  830. OldGetAPen(struct RastPort *RPort)
  831. {
  832.     return((ULONG)RPort->FgPen);
  833. }
  834.  
  835.     /* OldGetBPen(struct RastPort *RPort):
  836.      *
  837.      *    Query the current seconary rendering colour (old style).
  838.      */
  839.  
  840. ULONG
  841. OldGetBPen(struct RastPort *RPort)
  842. {
  843.     return((ULONG)RPort->BgPen);
  844. }
  845.  
  846.     /* OldGetDrMd(struct RastPort *RPort):
  847.      *
  848.      *    Query the current drawing mode (old style).
  849.      */
  850.  
  851. ULONG
  852. OldGetDrMd(struct RastPort *RPort)
  853. {
  854.     return((ULONG)RPort->DrawMode);
  855. }
  856.  
  857.     /* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
  858.      *
  859.      *    Set the rendering plane mask (old style).
  860.      */
  861.  
  862. ULONG
  863. OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
  864. {
  865.     if(UseMasking)
  866.         RPort->Mask = Mask;
  867.  
  868.     return((ULONG)1);
  869. }
  870.  
  871.     /* OldGetWrMsk(struct RastPort *RPort):
  872.      *
  873.      *    Get the rendering plane mask (old style).
  874.      */
  875.  
  876. ULONG
  877. OldGetWrMsk(struct RastPort *RPort)
  878. {
  879.     return(RPort->Mask);
  880. }
  881.  
  882.     /* NewGetAPen(struct RastPort *RPort):
  883.      *
  884.      *    Query the current primary rendering colour (new style).
  885.      */
  886.  
  887. ULONG
  888. NewGetAPen(struct RastPort *RPort)
  889. {
  890.     return(GetAPen(RPort));
  891. }
  892.  
  893.     /* NewGetBPen(struct RastPort *RPort):
  894.      *
  895.      *    Query the current seconary rendering colour (new style).
  896.      */
  897.  
  898. ULONG
  899. NewGetBPen(struct RastPort *RPort)
  900. {
  901.     return(GetBPen(RPort));
  902. }
  903.  
  904.     /* NewGetDrMd(struct RastPort *RPort):
  905.      *
  906.      *    Query the current drawing mode (new style).
  907.      */
  908.  
  909. ULONG
  910. NewGetDrMd(struct RastPort *RPort)
  911. {
  912.     return(GetDrMd(RPort));
  913. }
  914.  
  915.     /* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
  916.      *
  917.      *    Set the rendering plane mask (new style).
  918.      */
  919.  
  920. ULONG
  921. NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
  922. {
  923.     if(UseMasking)
  924.         return(SetWriteMask(RPort,Mask));
  925.     else
  926.         return((ULONG)1);
  927. }
  928.  
  929.     /* NewGetWrMsk(struct RastPort *RPort):
  930.      *
  931.      *    Get the rendering plane mask (new style).
  932.      */
  933.  
  934. ULONG
  935. NewGetWrMsk(struct RastPort *RPort)
  936. {
  937.     ULONG Mask;
  938.  
  939.     Mask = (ULONG)~0;
  940.  
  941.     GetRPAttrs(RPort,
  942.         RPTAG_WriteMask,&Mask,
  943.     TAG_DONE);
  944.  
  945.     return(Mask);
  946. }
  947.  
  948.     /* SetWait(struct Window *Window):
  949.      *
  950.      *    Set the busy wait mouse pointer.
  951.      */
  952.  
  953. VOID
  954. SetWait(struct Window *Window)
  955. {
  956.     if(GTLayoutBase)
  957.         LT_LockWindow(Window);
  958. }
  959.  
  960.     /* ClrWait(struct Window *Window):
  961.      *
  962.      *    Remove the busy wait mouse pointer.
  963.      */
  964.  
  965. VOID
  966. ClrWait(struct Window *Window)
  967. {
  968.     if(GTLayoutBase)
  969.         LT_UnlockWindow(Window);
  970. }
  971.  
  972.     /* GetModeName(ULONG Mode):
  973.      *
  974.      *    Get the name of a display mode.
  975.      */
  976.  
  977. VOID
  978. GetModeName(ULONG Mode,STRPTR Buffer,LONG BufferSize)
  979. {
  980.     struct NameInfo    NameInfo;
  981.  
  982.     if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
  983.         LimitedStrcpy(BufferSize,Buffer,NameInfo.Name);
  984.     else
  985.     {
  986.         struct DimensionInfo DimensionInfo;
  987.  
  988.         if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
  989.         {
  990.             STRPTR MonitorName;
  991.  
  992.             switch(Mode & MONITOR_ID_MASK)
  993.             {
  994.                 case NTSC_MONITOR_ID:
  995.  
  996.                     MonitorName = "NTSC:";
  997.                     break;
  998.  
  999.                 case PAL_MONITOR_ID:
  1000.  
  1001.                     MonitorName = "PAL:";
  1002.                     break;
  1003.  
  1004.                 case VGA_MONITOR_ID:
  1005.  
  1006.                     MonitorName = "VGA:";
  1007.                     break;
  1008.  
  1009.                 case A2024_MONITOR_ID:
  1010.  
  1011.                     MonitorName = "A2024:";
  1012.                     break;
  1013.  
  1014.                 default:
  1015.  
  1016.                     MonitorName = "";
  1017.                     break;
  1018.             }
  1019.  
  1020.             LimitedSPrintf(BufferSize,Buffer,"%s%ldx%ld",MonitorName,DimensionInfo.TxtOScan.MaxX - DimensionInfo.TxtOScan.MinX + 1,DimensionInfo.TxtOScan.MaxY - DimensionInfo.TxtOScan.MinY + 1);
  1021.         }
  1022.         else
  1023.             LimitedStrcpy(BufferSize,Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
  1024.     }
  1025. }
  1026.  
  1027.     /* ModeOkay(ULONG ID):
  1028.      *
  1029.      *    Checks whether a display mode ID will do for deep
  1030.      *    screen bitmaps.
  1031.      */
  1032.  
  1033. BOOL
  1034. ModeOkay(ULONG ID)
  1035. {
  1036.     struct DimensionInfo DimensionInfo;
  1037.  
  1038.     if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
  1039.     {
  1040.         if(DimensionInfo.MaxDepth >= 4)
  1041.             return(TRUE);
  1042.     }
  1043.  
  1044.     return(FALSE);
  1045. }
  1046.  
  1047.     /* ExtractString():
  1048.      *
  1049.      *    Extracts a string from a list separated by `|' characters.
  1050.      */
  1051.  
  1052. STRPTR
  1053. ExtractString(STRPTR String,STRPTR Destination,BOOL ReturnEnd)
  1054. {
  1055.     STRPTR OldString;
  1056.  
  1057.     if(ReturnEnd)
  1058.         OldString = NULL;
  1059.     else
  1060.         OldString = String;
  1061.  
  1062.     while(*String)
  1063.     {
  1064.         if(*String == '|')
  1065.         {
  1066.             *Destination = 0;
  1067.  
  1068.             String++;
  1069.  
  1070.             if(*String)
  1071.                 return(String);
  1072.             else
  1073.                 return(OldString);
  1074.         }
  1075.         else
  1076.             *Destination++ = *String++;
  1077.     }
  1078.  
  1079.     *Destination = 0;
  1080.  
  1081.     return(OldString);
  1082. }
  1083.  
  1084.     /* RemoveGetNext(struct Node *Node):
  1085.      *
  1086.      *    Remove a node from a list and return the `next'
  1087.      *    node to take its place.
  1088.      */
  1089.  
  1090. struct Node *
  1091. RemoveGetNext(struct Node *Node)
  1092. {
  1093.     struct Node *Next;
  1094.  
  1095.         /* Does the node have a successor? */
  1096.  
  1097.     if(Node->ln_Succ->ln_Succ)
  1098.         Next = Node->ln_Succ;
  1099.     else
  1100.     {
  1101.             /* Does it have a predecessor? */
  1102.  
  1103.         if(Node->ln_Pred->ln_Pred)
  1104.             Next = Node->ln_Pred;
  1105.         else
  1106.             Next = NULL;
  1107.     }
  1108.  
  1109.         /* Remove the old node. */
  1110.  
  1111.     Remove(Node);
  1112.  
  1113.         /* And return the node to take its place. */
  1114.  
  1115.     return(Next);
  1116. }
  1117.  
  1118.     /* GetListSize(struct List *List):
  1119.      *
  1120.      *    Determine the number of entries in a list.
  1121.      */
  1122.  
  1123. LONG
  1124. GetListSize(struct List *List)
  1125. {
  1126.     struct Node *Node;
  1127.     LONG i;
  1128.  
  1129.     for(Node = List->lh_Head, i = 0 ; Node->ln_Succ ; Node = Node->ln_Succ, i++);
  1130.  
  1131.     return(i);
  1132. }
  1133.  
  1134.     /* GetListNode(LONG Offset,struct List *List):
  1135.      *
  1136.      *    Return the n-th Node entry in a standard exec list.
  1137.      */
  1138.  
  1139. struct Node *
  1140. GetListNode(LONG Offset,struct List *List)
  1141. {
  1142.     struct Node *Node;
  1143.     LONG Index;
  1144.  
  1145.     for(Node = List->lh_Head, Index = 0 ; Node->ln_Succ ; Node = Node->ln_Succ, Index++)
  1146.     {
  1147.         if(Index == Offset)
  1148.             return(Node);
  1149.     }
  1150.  
  1151.     return(NULL);
  1152. }
  1153.  
  1154.     /* CreateNode(STRPTR Name):
  1155.      *
  1156.      *    Put a name string into a list node.
  1157.      */
  1158.  
  1159. struct Node *
  1160. CreateNode(STRPTR Name)
  1161. {
  1162.     struct Node *Node;
  1163.  
  1164.     if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(Name) + 1,MEMF_ANY))
  1165.         strcpy(Node->ln_Name = (STRPTR)(Node + 1),Name);
  1166.  
  1167.     return(Node);
  1168. }
  1169.  
  1170.     /* CreateNodeArgs(STRPTR Format,...):
  1171.      *
  1172.      *    Put a name string into a list node, varargs version.
  1173.      */
  1174.  
  1175. struct Node *
  1176. CreateNodeArgs(STRPTR Format,...)
  1177. {
  1178.     UBYTE LocalBuffer[256];
  1179.     struct Node *Node;
  1180.     va_list VarArgs;
  1181.  
  1182.     va_start(VarArgs,Format);
  1183.     LimitedVSPrintf(sizeof(LocalBuffer),LocalBuffer,Format,VarArgs);
  1184.     va_end(VarArgs);
  1185.  
  1186.     if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(LocalBuffer) + 1,MEMF_ANY))
  1187.         strcpy(Node->ln_Name = (STRPTR)(Node + 1),LocalBuffer);
  1188.  
  1189.     return(Node);
  1190. }
  1191.  
  1192.     /* FormatAppend(STRPTR String,STRPTR Format,...):
  1193.      *
  1194.      *    Appends a formatted string to another string.
  1195.      */
  1196.  
  1197. VOID
  1198. FormatAppend(STRPTR String,STRPTR Format,...)
  1199. {
  1200.     va_list VarArgs;
  1201.  
  1202.     String += strlen(String);
  1203.  
  1204.     va_start(VarArgs,Format);
  1205.     VSPrintf(String,Format,VarArgs);
  1206.     va_end(VarArgs);
  1207. }
  1208.  
  1209.     /* FreeList(struct List *List):
  1210.      *
  1211.      *    Remove all nodes from the list
  1212.      *    and free them on the way.
  1213.      */
  1214.  
  1215. VOID
  1216. FreeList(struct List *List)
  1217. {
  1218.     if(List)
  1219.     {
  1220.         struct Node *Node;
  1221.  
  1222.         while(Node = RemHead(List))
  1223.             FreeVecPooled(Node);
  1224.     }
  1225. }
  1226.  
  1227.     /* GetNodeOffset(struct Node *Node,struct List *List):
  1228.      *
  1229.      *    Scan a list for a certain node and return
  1230.      *    its position.
  1231.      */
  1232.  
  1233. LONG
  1234. GetNodeOffset(struct Node *ListNode,struct List *List)
  1235. {
  1236.     if(ListNode && List)
  1237.     {
  1238.         struct Node *Node;
  1239.         LONG Offset;
  1240.  
  1241.         for(Node = List->lh_Head, Offset = 0 ; Node->ln_Succ ; Node = Node->ln_Succ, Offset++)
  1242.         {
  1243.             if(Node == ListNode)
  1244.                 return(Offset);
  1245.         }
  1246.     }
  1247.  
  1248.     return(-1);
  1249. }
  1250.  
  1251.     /* MoveList(struct List *From,struct List *To):
  1252.      *
  1253.      *    Move the contents of a list to a different list.
  1254.      */
  1255.  
  1256. VOID
  1257. MoveList(struct List *From,struct List *To)
  1258. {
  1259.     struct Node *Node;
  1260.  
  1261.     while(Node = RemHead(From))
  1262.         AddTail(To,Node);
  1263. }
  1264.  
  1265.     /* CreateList():
  1266.      *
  1267.      *    Create a small, empty list.
  1268.      */
  1269.  
  1270. struct List *
  1271. CreateList()
  1272. {
  1273.     struct List *List;
  1274.  
  1275.     if(List = (struct List *)AllocVecPooled(sizeof(struct MinList),MEMF_ANY))
  1276.         NewList(List);
  1277.  
  1278.     return(List);
  1279. }
  1280.  
  1281.     /* DeleteList():
  1282.      *
  1283.      *    Free the contents of a list and the list itself.
  1284.      */
  1285.  
  1286. VOID
  1287. DeleteList(struct List *List)
  1288. {
  1289.     if(List)
  1290.     {
  1291.         struct Node *Node,*Next;
  1292.  
  1293.         for(Node = List->lh_Head ; Next = Node->ln_Succ ; Node = Next)
  1294.             FreeVecPooled(Node);
  1295.  
  1296.         FreeVecPooled(List);
  1297.     }
  1298. }
  1299.  
  1300.     /* MoveNode(struct List *List,struct Node *Node,LONG How):
  1301.      *
  1302.      *    Move a list node somewhere.
  1303.      */
  1304.  
  1305. VOID
  1306. MoveNode(struct List *List,struct Node *Node,LONG How)
  1307. {
  1308.     switch(How)
  1309.     {
  1310.         case MOVE_HEAD:
  1311.  
  1312.             if(Node != List->lh_Head)
  1313.             {
  1314.                 Remove(Node);
  1315.  
  1316.                 AddHead(List,Node);
  1317.             }
  1318.  
  1319.             break;
  1320.  
  1321.         case MOVE_PRED:
  1322.  
  1323.             if(Node != List->lh_Head)
  1324.             {
  1325.                 struct Node *Other;
  1326.  
  1327.                 Other = Node->ln_Pred->ln_Pred;
  1328.  
  1329.                 Remove(Node);
  1330.  
  1331.                 Insert(List,Node,Other);
  1332.             }
  1333.  
  1334.             break;
  1335.  
  1336.         case MOVE_SUCC:
  1337.  
  1338.             if(Node != List->lh_TailPred)
  1339.             {
  1340.                 struct Node *Other;
  1341.  
  1342.                 Other = Node->ln_Succ;
  1343.  
  1344.                 Remove(Node);
  1345.  
  1346.                 Insert(List,Node,Other);
  1347.             }
  1348.  
  1349.             break;
  1350.  
  1351.         case MOVE_TAIL:
  1352.  
  1353.             if(Node != List->lh_TailPred)
  1354.             {
  1355.                 Remove(Node);
  1356.  
  1357.                 AddTail(List,Node);
  1358.             }
  1359.  
  1360.             break;
  1361.     }
  1362. }
  1363.  
  1364.     /* LogAction(STRPTR String,...):
  1365.      *
  1366.      *    Write an action to the default log file.
  1367.      */
  1368.  
  1369. VOID
  1370. LogAction(STRPTR String,...)
  1371. {
  1372.     if(Config->CaptureConfig->LogActions && Config->CaptureConfig->LogFileName[0])
  1373.     {
  1374.         UBYTE    DummyBuffer[512];
  1375.         BPTR    File;
  1376.         BOOL    Created;
  1377.  
  1378.         va_list    VarArgs;
  1379.  
  1380.             /* Build a valid string. */
  1381.  
  1382.         va_start(VarArgs,String);
  1383.         LimitedVSPrintf(sizeof(DummyBuffer),DummyBuffer,String,VarArgs);
  1384.         va_end(VarArgs);
  1385.  
  1386.             /* Open the log file. */
  1387.  
  1388.         if(File = OpenToAppend(Config->CaptureConfig->LogFileName,&Created))
  1389.         {
  1390.             if(Created)
  1391.                 FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
  1392.         }
  1393.  
  1394.             /* The file is open, build the date/time string and
  1395.              * write the log action.
  1396.              */
  1397.  
  1398.         if(File)
  1399.         {
  1400.             UBYTE            DateBuffer[40],
  1401.                             TimeBuffer[40];
  1402.             struct DateTime    DateTime;
  1403.  
  1404.             DateStamp(&DateTime.dat_Stamp);
  1405.  
  1406.             DateTime.dat_Format        = FORMAT_DEF;
  1407.             DateTime.dat_Flags        = NULL;
  1408.             DateTime.dat_StrDay        = NULL;
  1409.             DateTime.dat_StrDate    = DateBuffer;
  1410.             DateTime.dat_StrTime    = TimeBuffer;
  1411.  
  1412.             if(DateToStr(&DateTime))
  1413.             {
  1414.                 StripSpaces(TimeBuffer);
  1415.  
  1416.                 FPrintf(File,"%-9s %8s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
  1417.             }
  1418.  
  1419.                 /* Done! */
  1420.  
  1421.             Close(File);
  1422.         }
  1423.     }
  1424. }
  1425.  
  1426.     /* GetString(STRPTR Prompt,STRPTR Buffer):
  1427.      *
  1428.      *    Get a string from the user, very much the same as xpr_gets.
  1429.      */
  1430.  
  1431. BOOL
  1432. GetString(BOOL LoadGadget,BOOL Password,LONG MaxChars,STRPTR Prompt,STRPTR Buffer)
  1433. {
  1434.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  1435.  
  1436.     struct LayoutHandle    *Handle;
  1437.     UBYTE LocalBuffer[256];
  1438.     BOOL Success = FALSE;
  1439.  
  1440.     if(!MaxChars)
  1441.         MaxChars = sizeof(LocalBuffer) - 1;
  1442.  
  1443.     if(MaxChars > sizeof(LocalBuffer) - 1)
  1444.     {
  1445.         CopyMem(Buffer,LocalBuffer,sizeof(LocalBuffer) - 1);
  1446.  
  1447.         LocalBuffer[sizeof(LocalBuffer) - 1] = 0;
  1448.  
  1449.         MaxChars = sizeof(LocalBuffer) - 1;
  1450.     }
  1451.     else
  1452.         strcpy(LocalBuffer,Buffer);
  1453.  
  1454.     if(!Prompt)
  1455.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1456.  
  1457.     if(Handle = LT_CreateHandleTags(Window->WScreen,
  1458.         LAHN_LocaleHook,    &LocaleHook,
  1459.     TAG_DONE))
  1460.     {
  1461.         struct Window *PanelWindow;
  1462.  
  1463.         LT_New(Handle,
  1464.             LA_Type,    VERTICAL_KIND,
  1465.         TAG_DONE);
  1466.         {
  1467.             LT_New(Handle,
  1468.                 LA_Type,    VERTICAL_KIND,
  1469.                 LA_LabelText,    Prompt,
  1470.             TAG_DONE);
  1471.             {
  1472.                 if(Password)
  1473.                 {
  1474.                     LT_New(Handle,
  1475.                         LA_Type,        PASSWORD_KIND,
  1476.                         LA_STRPTR,        LocalBuffer,
  1477.                         LA_ID,            GAD_STRING,
  1478.                         LA_Chars,        40,
  1479.                         GTST_MaxChars,    MaxChars,
  1480.                     TAG_DONE);
  1481.                 }
  1482.                 else
  1483.                 {
  1484.                     LT_New(Handle,
  1485.                         LA_Type,        STRING_KIND,
  1486.                         LA_STRPTR,        LocalBuffer,
  1487.                         LA_ID,            GAD_STRING,
  1488.                         LA_Chars,        60,
  1489.                         LAST_Picker,    LoadGadget,
  1490.                     TAG_DONE);
  1491.                 }
  1492.  
  1493.                 LT_EndGroup(Handle);
  1494.             }
  1495.  
  1496.             LT_New(Handle,
  1497.                 LA_Type,VERTICAL_KIND,
  1498.             TAG_DONE);
  1499.             {
  1500.                 LT_New(Handle,
  1501.                     LA_Type,        XBAR_KIND,
  1502.                     LAXB_FullSize,    TRUE,
  1503.                 TAG_DONE);
  1504.  
  1505.                 LT_EndGroup(Handle);
  1506.             }
  1507.  
  1508.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  1509.                 LAGR_SameSize,    TRUE,
  1510.                 LAGR_Spread,    TRUE,
  1511.             TAG_DONE);
  1512.             {
  1513.                 LT_New(Handle,
  1514.                     LA_Type,        BUTTON_KIND,
  1515.                     LA_LabelID,        MSG_TERMXPR_OKAY_GAD,
  1516.                     LA_ID,            GAD_OK,
  1517.                     LABT_ReturnKey,    TRUE,
  1518.                     LABT_ExtraFat,    TRUE,
  1519.                 TAG_DONE);
  1520.  
  1521.                 LT_New(Handle,
  1522.                     LA_Type,        BUTTON_KIND,
  1523.                     LA_LabelID,        MSG_GLOBAL_CANCEL_GAD,
  1524.                     LA_ID,            GAD_CANCEL,
  1525.                     LABT_EscKey,    TRUE,
  1526.                     LABT_ExtraFat,    TRUE,
  1527.                 TAG_DONE);
  1528.  
  1529.                 LT_EndGroup(Handle);
  1530.             }
  1531.         }
  1532.  
  1533.         if(PanelWindow = LT_Build(Handle,
  1534.             LAWN_TitleID,        MSG_GLOBAL_ENTER_TEXT_TXT,
  1535.             LAWN_HelpHook,        &GuideHook,
  1536.             LAWN_Parent,        Window,
  1537.             WA_DepthGadget,        TRUE,
  1538.             WA_DragBar,            TRUE,
  1539.             WA_RMBTrap,            TRUE,
  1540.             WA_Activate,        TRUE,
  1541.             WA_SimpleRefresh,    TRUE,
  1542.         TAG_DONE))
  1543.         {
  1544.             struct IntuiMessage    *Message;
  1545.             BOOL                 Done = FALSE;
  1546.             ULONG                 MsgClass;
  1547.             UWORD                 MsgCode;
  1548.             struct Gadget        *MsgGadget;
  1549.  
  1550.             LT_Activate(Handle,GAD_STRING);
  1551.  
  1552.             PushWindow(PanelWindow);
  1553.  
  1554.             LT_ShowWindow(Handle,TRUE);
  1555.  
  1556.             do
  1557.             {
  1558.                 if(Wait(PORTMASK(PanelWindow->UserPort) | SIG_BREAK) & SIG_BREAK)
  1559.                     break;
  1560.  
  1561.                 while(Message = (struct IntuiMessage *)LT_GetIMsg(Handle))
  1562.                 {
  1563.                     MsgClass    = Message->Class;
  1564.                     MsgCode        = Message->Code;
  1565.                     MsgGadget    = (struct Gadget *)Message->IAddress;
  1566.  
  1567.                     LT_ReplyIMsg(Message);
  1568.  
  1569.                     if(MsgClass == IDCMP_GADGETUP)
  1570.                     {
  1571.                         switch(MsgGadget->GadgetID)
  1572.                         {
  1573.                             case GAD_STRING:
  1574.  
  1575.                                 if(MsgCode == '\r')
  1576.                                 {
  1577.                                     LT_UpdateStrings(Handle);
  1578.  
  1579.                                     strcpy(Buffer,LocalBuffer);
  1580.  
  1581.                                     Success = Done = TRUE;
  1582.  
  1583.                                     LT_PressButton(Handle,GAD_OK);
  1584.                                 }
  1585.  
  1586.                                 break;
  1587.  
  1588.                             case GAD_OK:
  1589.  
  1590.                                 LT_UpdateStrings(Handle);
  1591.  
  1592.                                 strcpy(Buffer,LocalBuffer);
  1593.  
  1594.                                 Success = Done = TRUE;
  1595.                                 break;
  1596.  
  1597.                             case GAD_CANCEL:
  1598.  
  1599.                                 Done = TRUE;
  1600.                                 break;
  1601.                         }
  1602.                     }
  1603.  
  1604.                     if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadget->GadgetID == GAD_STRING)
  1605.                     {
  1606.                         UBYTE DummyBuffer[MAX_FILENAME_LENGTH];
  1607.                         struct FileRequester *FileRequest;
  1608.  
  1609.                         strcpy(DummyBuffer,LocalBuffer);
  1610.  
  1611.                         if(FileRequest = OpenSingleFile(PanelWindow,LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),NULL,NULL,DummyBuffer,sizeof(DummyBuffer)))
  1612.                         {
  1613.                             FreeAslRequest(FileRequest);
  1614.  
  1615.                             LT_SetAttributes(Handle,GAD_STRING,
  1616.                                 GTST_String,    DummyBuffer,
  1617.                             TAG_DONE);
  1618.                         }
  1619.                     }
  1620.                 }
  1621.             }
  1622.             while(!Done);
  1623.  
  1624.             PopWindow();
  1625.         }
  1626.  
  1627.         LT_DeleteHandle(Handle);
  1628.     }
  1629.  
  1630.     return(Success);
  1631. }
  1632.  
  1633.     /* WakeUp(struct Window *Window,LONG Sound):
  1634.      *
  1635.      *    Pop a window to the front and alert the user.
  1636.      */
  1637.  
  1638. VOID
  1639. WakeUp(struct Window *Window,LONG Sound)
  1640. {
  1641.     if(Window)
  1642.     {
  1643.         if(Config->MiscConfig->AlertMode == ALERT_SCREEN || Config->MiscConfig->AlertMode == ALERT_BEEP_SCREEN)
  1644.         {
  1645.             if(Window->WScreen->LeftEdge > 0)
  1646.             {
  1647.                 if(Window->WScreen->TopEdge > 0)
  1648.                     MoveScreen(Window->WScreen,-Window->WScreen->LeftEdge,-Window->WScreen->TopEdge);
  1649.                 else
  1650.                     MoveScreen(Window->WScreen,-Window->WScreen->LeftEdge,0);
  1651.             }
  1652.             else
  1653.             {
  1654.                 if(Window->WScreen->TopEdge > 0)
  1655.                     MoveScreen(Window->WScreen,0,-Window->WScreen->TopEdge);
  1656.             }
  1657.  
  1658.             WindowToFront(Window);
  1659.  
  1660.             ScreenToFront(Window->WScreen);
  1661.         }
  1662.     }
  1663.  
  1664.     if(Sound != SOUND_BELL || Config->MiscConfig->AlertMode == ALERT_BEEP || Config->MiscConfig->AlertMode == ALERT_BEEP_SCREEN)
  1665.         SoundPlay(Sound);
  1666. }
  1667.  
  1668.     /* BlockWindows():
  1669.      *
  1670.      *    Block the main window and the status window (i.e. disable
  1671.      *    the menu and attach a wait pointer).
  1672.      */
  1673.  
  1674. VOID
  1675. BlockWindows()
  1676. {
  1677.     if(!(BlockNestCount++))
  1678.     {
  1679.         LT_LockWindow(Window);
  1680.         LT_LockWindow(StatusWindow);
  1681.         LT_LockWindow(FastWindow);
  1682.         LT_LockWindow(MatrixWindow);
  1683.  
  1684.         WeAreBlocking = TRUE;
  1685.  
  1686.         SetQueueDiscard(SpecialQueue,TRUE);
  1687.  
  1688.         GhostCursor();
  1689.     }
  1690. }
  1691.  
  1692.     /* ReleaseWindows():
  1693.      *
  1694.      *    Reenable the menus and clear the wait pointer.
  1695.      */
  1696.  
  1697. VOID
  1698. ReleaseWindows()
  1699. {
  1700.     if(BlockNestCount == 1)
  1701.     {
  1702.         LT_UnlockWindow(Window);
  1703.         LT_UnlockWindow(StatusWindow);
  1704.         LT_UnlockWindow(FastWindow);
  1705.         LT_UnlockWindow(MatrixWindow);
  1706.  
  1707.         WeAreBlocking = FALSE;
  1708.  
  1709.         SetQueueDiscard(SpecialQueue,FALSE);
  1710.  
  1711.         if(Window)
  1712.         {
  1713.             Forbid();
  1714.  
  1715.             if(Window->Flags & WFLG_WINDOWACTIVE)
  1716.                 NormalCursor();
  1717.  
  1718.             Permit();
  1719.         }
  1720.     }
  1721.  
  1722.     if(BlockNestCount)
  1723.         BlockNestCount--;
  1724. }
  1725.  
  1726.     /* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
  1727.      *
  1728.      *    Read a few bytes from a file (à la gets).
  1729.      */
  1730.  
  1731. LONG
  1732. LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
  1733. {
  1734.     STATIC UBYTE    Data[1024];
  1735.     STATIC LONG        ReadIndex,ReadLen;
  1736.  
  1737.     LONG BytesRead = 0;
  1738.  
  1739.     if(File)
  1740.     {
  1741.         LONG i;
  1742.  
  1743.         for(i = 0 ; i < MaxChars ; i++)
  1744.         {
  1745.             if(ReadIndex >= ReadLen)
  1746.             {
  1747.                 ReadLen = Read(File,Data,sizeof(Data));
  1748.  
  1749.                 ReadIndex = 0;
  1750.  
  1751.                 if(ReadLen <= 0)
  1752.                 {
  1753.                     Buffer[i] = 0;
  1754.                     break;
  1755.                 }
  1756.             }
  1757.  
  1758.             BytesRead++;
  1759.  
  1760.             if((Buffer[i] = Data[ReadIndex++]) == '\n')
  1761.             {
  1762.                 Buffer[i + 1] = 0;
  1763.  
  1764.                 break;
  1765.             }
  1766.         }
  1767.     }
  1768.     else
  1769.         ReadIndex = ReadLen = 0;
  1770.  
  1771.     return(BytesRead);
  1772. }
  1773.  
  1774.     /* GetBaudRate(STRPTR Buffer):
  1775.      *
  1776.      *    Calculate the baud rate contained in a connect string.
  1777.      */
  1778.  
  1779. LONG
  1780. GetBaudRate(STRPTR Buffer)
  1781. {
  1782.     UBYTE LocalBuffer[40];
  1783.     LONG Rate,i,j;
  1784.  
  1785.     for(i = j = 0 ; i < strlen(Buffer) ; i++)
  1786.     {
  1787.         if(Buffer[i] == ' ')
  1788.             continue;
  1789.         else
  1790.         {
  1791.             if(Buffer[i] >= '0' && Buffer[i] <= '9')
  1792.                 LocalBuffer[j++] = Buffer[i];
  1793.             else
  1794.                 break;
  1795.         }
  1796.     }
  1797.  
  1798.     LocalBuffer[j] = 0;
  1799.  
  1800.     if(StrToLong(LocalBuffer,&Rate) > 0)
  1801.     {
  1802.         if(Rate > 0)
  1803.             return(Rate);
  1804.     }
  1805.  
  1806.     return(0);
  1807. }
  1808.  
  1809.     /* GetFileSize(STRPTR Name):
  1810.      *
  1811.      *    Simple routine to return the size of a file in
  1812.      *    bytes.
  1813.      */
  1814.  
  1815. LONG
  1816. GetFileSize(STRPTR Name)
  1817. {
  1818.     BPTR FileLock;
  1819.     LONG FileSize = 0;
  1820.     D_S(struct FileInfoBlock,FileInfo);
  1821.  
  1822.     if(FileLock = Lock(Name,ACCESS_READ))
  1823.     {
  1824.         if(Examine(FileLock,FileInfo))
  1825.         {
  1826.             if(FileInfo->fib_DirEntryType < 0)
  1827.                 FileSize = FileInfo->fib_Size;
  1828.         }
  1829.  
  1830.         UnLock(FileLock);
  1831.     }
  1832.  
  1833.     return(FileSize);
  1834. }
  1835.  
  1836.     /* PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height):
  1837.      *
  1838.      *    Put back the default values for the requesters to open.
  1839.      */
  1840.  
  1841. VOID
  1842. PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height)
  1843. {
  1844.     if(Config->MiscConfig->RequesterMode != REQUESTERMODE_IGNORE && (!Config->MiscConfig->RequesterWidth || !Config->MiscConfig->RequesterHeight))
  1845.     {
  1846.         if(!Reference)
  1847.             Reference = Window;
  1848.  
  1849.         Config->MiscConfig->RequesterLeft    = Left    - Reference->LeftEdge;
  1850.         Config->MiscConfig->RequesterTop    = Top    - Reference->TopEdge;
  1851.         Config->MiscConfig->RequesterWidth    = Width;
  1852.         Config->MiscConfig->RequesterHeight    = Height;
  1853.     }
  1854. }
  1855.  
  1856.     /* GetDimensionTags(struct Window *Reference,struct TagItem *Tags):
  1857.      *
  1858.      *    Fills an array of tagitems with the dimensions of an asl requester
  1859.      *    to be opened.
  1860.      */
  1861.  
  1862. struct TagItem *
  1863. GetDimensionTags(struct Window *Reference,struct TagItem *Tags)
  1864. {
  1865.     if(Config->MiscConfig->RequesterMode == REQUESTERMODE_IGNORE || Config->MiscConfig->RequesterWidth < 1 || Config->MiscConfig->RequesterHeight < 1)
  1866.     {
  1867.         STATIC ULONG Done = TAG_DONE;
  1868.  
  1869.         return((struct TagItem *)&Done);
  1870.     }
  1871.     else
  1872.     {
  1873.         LONG Left,Top,Width,Height;
  1874.  
  1875.         if(!Reference)
  1876.             Reference = Window;
  1877.  
  1878.         if(Config->MiscConfig->RequesterMode == REQUESTERMODE_CENTRE)
  1879.         {
  1880.             Left    = Reference->LeftEdge    + (Reference->Width - Config->MiscConfig->RequesterWidth) / 2;
  1881.             Top        = Reference->TopEdge    + (Reference->Height - Config->MiscConfig->RequesterHeight) / 2;
  1882.         }
  1883.         else
  1884.         {
  1885.             Left    = Config->MiscConfig->RequesterLeft    + Reference->LeftEdge;
  1886.             Top        = Config->MiscConfig->RequesterTop    + Reference->TopEdge;
  1887.         }
  1888.  
  1889.         Width    = Config->MiscConfig->RequesterWidth;
  1890.         Height    = Config->MiscConfig->RequesterHeight;
  1891.  
  1892.         Tags[0].ti_Tag    = ASL_LeftEdge;
  1893.         Tags[0].ti_Data    = Left;
  1894.         Tags[1].ti_Tag    = ASL_TopEdge;
  1895.         Tags[1].ti_Data    = Top;
  1896.         Tags[2].ti_Tag    = ASL_Width;
  1897.         Tags[2].ti_Data    = Width;
  1898.         Tags[3].ti_Tag    = ASL_Height;
  1899.         Tags[3].ti_Data    = Height;
  1900.         Tags[4].ti_Tag    = TAG_DONE;
  1901.  
  1902.         return(Tags);
  1903.     }
  1904. }
  1905.  
  1906.     /* ShowRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
  1907.      *
  1908.      *    Really quite simple varargs version of Intuition's
  1909.      *    EasyRequest requester.
  1910.      */
  1911.  
  1912. LONG
  1913. ShowRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...)
  1914. {
  1915.     struct EasyStruct Easy;
  1916.     va_list VarArgs;
  1917.     LONG i,GadgetCount;
  1918.  
  1919.     for(i = GadgetCount = 0 ; i < strlen(Gadgets) ; i++)
  1920.     {
  1921.         if(Gadgets[i] == '|')
  1922.             GadgetCount++;
  1923.     }
  1924.  
  1925.         /* Standard data. */
  1926.  
  1927.     Easy.es_StructSize        = sizeof(struct EasyStruct);
  1928.     Easy.es_Flags            = NULL;
  1929.     Easy.es_Title            = LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
  1930.     Easy.es_TextFormat        = Text;
  1931.     Easy.es_GadgetFormat    = Gadgets;
  1932.  
  1933.     if(GadgetCount)
  1934.     {
  1935.         LONG Result;
  1936.  
  1937.         if(GTLayoutBase)
  1938.             LT_LockWindow(Window);
  1939.  
  1940.             /* Use the argument array to build the
  1941.              * requester and display it.
  1942.              */
  1943.  
  1944.         va_start(VarArgs,Gadgets);
  1945.         Result = EasyRequestArgs(Window,&Easy,NULL,(APTR)VarArgs);
  1946.         va_end(VarArgs);
  1947.  
  1948.         if(GTLayoutBase)
  1949.             LT_UnlockWindow(Window);
  1950.  
  1951.         return(Result);
  1952.     }
  1953.     else
  1954.     {
  1955.         struct Window *ReqWindow;
  1956.  
  1957.         if(GTLayoutBase)
  1958.             LT_LockWindow(Window);
  1959.  
  1960.         va_start(VarArgs,Gadgets);
  1961.  
  1962.         if(ReqWindow = BuildEasyRequestArgs(Window,&Easy,IDCMP_RAWKEY,(APTR)VarArgs))
  1963.         {
  1964.             ULONG    IDCMP;
  1965.             LONG    Result;
  1966.  
  1967.             FOREVER
  1968.             {
  1969.                 WaitPort(ReqWindow->UserPort);
  1970.  
  1971.                 IDCMP = NULL;
  1972.  
  1973.                 Result = SysReqHandler(ReqWindow,&IDCMP,FALSE);
  1974.  
  1975.                 if(!Result || (Result == -2 && !(IDCMP & IDCMP_RAWKEY)))
  1976.                     break;
  1977.             }
  1978.  
  1979.             FreeSysRequest(ReqWindow);
  1980.         }
  1981.  
  1982.         va_end(VarArgs);
  1983.  
  1984.         if(GTLayoutBase)
  1985.             LT_UnlockWindow(Window);
  1986.  
  1987.         return(0);
  1988.     }
  1989. }
  1990.  
  1991.     /* CloseWindowSafely(struct Window *Window):
  1992.      *
  1993.      *    Close a window freeing all messages pending at
  1994.      *    its user port (taken from example source code
  1995.      *    published once upon a time in Amiga Mail).
  1996.      */
  1997.  
  1998. VOID
  1999. CloseWindowSafely(struct Window *Window)
  2000. {
  2001.     Forbid();
  2002.  
  2003.     if(Window->UserPort)
  2004.     {
  2005.         struct Node *Node,*Next;
  2006.  
  2007.         for(Node = Window->UserPort->mp_MsgList.lh_Head ; Next = Node->ln_Succ ; Node = Next)
  2008.         {
  2009.             if(((struct IntuiMessage *)Node)->IDCMPWindow == Window)
  2010.             {
  2011.                 Remove(Node);
  2012.                 ReplyMsg((struct Message *)Node);
  2013.             }
  2014.         }
  2015.  
  2016.         Window->UserPort = NULL;
  2017.     }
  2018.  
  2019.     ModifyIDCMP(Window,NULL);
  2020.  
  2021.     Permit();
  2022.  
  2023.     LT_DeleteWindowLock(Window);
  2024.  
  2025.     CloseWindow(Window);
  2026. }
  2027.  
  2028.     /* DelayTime(LONG Secs,LONG Micros):
  2029.      *
  2030.      *    Delay for a given period of time.
  2031.      */
  2032.  
  2033. VOID
  2034. DelayTime(LONG Secs,LONG Micros)
  2035. {
  2036.     StopTime();
  2037.  
  2038.     if(Secs || Micros)
  2039.     {
  2040.         StartTime(Secs,Micros);
  2041.  
  2042.         WaitTime();
  2043.     }
  2044. }
  2045.  
  2046.     /* WaitTime():
  2047.      *
  2048.      *    Wait for a pending time request to finish.
  2049.      */
  2050.  
  2051. VOID
  2052. WaitTime()
  2053. {
  2054.     if(TimerRunning)
  2055.     {
  2056.         TimerRunning = FALSE;
  2057.  
  2058.         WaitIO((struct IORequest *)TimeRequest);
  2059.     }
  2060. }
  2061.  
  2062.     /* StopTime():
  2063.      *
  2064.      *    Stop the running timer.
  2065.      */
  2066.  
  2067. VOID
  2068. StopTime()
  2069. {
  2070.     if(TimerRunning)
  2071.     {
  2072.         if(!CheckIO((struct IORequest *)TimeRequest))
  2073.             AbortIO((struct IORequest *)TimeRequest);
  2074.  
  2075.         WaitIO((struct IORequest *)TimeRequest);
  2076.     }
  2077. }
  2078.  
  2079.     /* StartTime(LONG Secs,LONG Micros):
  2080.      *
  2081.      *    Start the timer asynchronously.
  2082.      */
  2083.  
  2084. VOID
  2085. StartTime(LONG Secs,LONG Micros)
  2086. {
  2087.     StopTime();
  2088.  
  2089.     if(Secs || Micros)
  2090.     {
  2091.         TimeRequest->tr_node.io_Command    = TR_ADDREQUEST;
  2092.         TimeRequest->tr_time.tv_secs    = Secs;
  2093.         TimeRequest->tr_time.tv_micro    = Micros;
  2094.  
  2095.         ClrSignal(SIG_TIMER);
  2096.  
  2097.         SendIO((struct IORequest *)TimeRequest);
  2098.  
  2099.         TimerRunning = TRUE;
  2100.     }
  2101. }
  2102.  
  2103.     /* GetEnvDOS(STRPTR Name,STRPTR Buffer):
  2104.      *
  2105.      *    Get the contents of a vanilla AmigaDOS environment
  2106.      *    variable.
  2107.      */
  2108.  
  2109. BOOL
  2110. GetEnvDOS(STRPTR Name,STRPTR Buffer,LONG BufferSize)
  2111. {
  2112.     if(GetVar(Name,Buffer,256,NULL) >= 0)
  2113.         return(TRUE);
  2114.     else
  2115.     {
  2116.         Buffer[0] = 0;
  2117.  
  2118.         return(FALSE);
  2119.     }
  2120. }
  2121.  
  2122.     /* SetEnvDOS(STRPTR Name,STRPTR Value):
  2123.      *
  2124.      *    Set the contents of a vanilla AmigaDOS environment
  2125.      *    variable.
  2126.      */
  2127.  
  2128. BOOL
  2129. SetEnvDOS(STRPTR Name,STRPTR Value)
  2130. {
  2131.     if(SetVar(Name,Value,-1,GVF_SAVE_VAR))
  2132.     {
  2133.             /* Ouch! Bug in dos.library V39! GVF_SAVE_VAR doesn't
  2134.              * work unless GVF_GLOBAL_ONLY is set as well.
  2135.              */
  2136.  
  2137. /*        if(Kick30)*/
  2138. /*            return(TRUE);*/
  2139. /*        else*/
  2140.         {
  2141.             UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  2142.             BOOL Result = FALSE;
  2143.  
  2144.             strcpy(LocalBuffer,"ENVARC:");
  2145.  
  2146.             if(AddPart(LocalBuffer,FilePart(Name),sizeof(LocalBuffer)))
  2147.             {
  2148.                 BPTR FileHandle;
  2149.  
  2150.                 if(!(FileHandle = Open(LocalBuffer,MODE_NEWFILE)))
  2151.                     Result = FALSE;
  2152.                 else
  2153.                 {
  2154.                     LONG Length = strlen(Value);
  2155.  
  2156.                     if(Write(FileHandle,Value,Length) == Length)
  2157.                         Result = TRUE;
  2158.  
  2159.                     Close(FileHandle);
  2160.                 }
  2161.             }
  2162.  
  2163.             return(Result);
  2164.         }
  2165.     }
  2166.  
  2167.     return(FALSE);
  2168. }
  2169.  
  2170.     /* BumpWindow(struct Window *SomeWindow):
  2171.      *
  2172.      *    Bring a window to the front (and shift the screen
  2173.      *    back to its initial position).
  2174.      */
  2175.  
  2176. VOID
  2177. BumpWindow(struct Window *SomeWindow)
  2178. {
  2179.     if(SomeWindow)
  2180.     {
  2181.         if(SomeWindow->WScreen->LeftEdge > 0)
  2182.         {
  2183.             if(SomeWindow->WScreen->TopEdge > 0)
  2184.                 MoveScreen(SomeWindow->WScreen,-SomeWindow->WScreen->LeftEdge,-SomeWindow->WScreen->TopEdge);
  2185.             else
  2186.                 MoveScreen(SomeWindow->WScreen,-SomeWindow->WScreen->LeftEdge,0);
  2187.         }
  2188.         else
  2189.         {
  2190.             if(SomeWindow->WScreen->TopEdge > 0)
  2191.                 MoveScreen(SomeWindow->WScreen,0,-SomeWindow->WScreen->TopEdge);
  2192.         }
  2193.  
  2194.         ScreenToFront(SomeWindow->WScreen);
  2195.  
  2196.         ActivateWindow(SomeWindow);
  2197.     }
  2198. }
  2199.  
  2200.     /* PushWindow(struct Window *Window):
  2201.      *
  2202.      *    Push/PopWindow implement a single lifo window stack
  2203.      *    which always updates the window to activate when
  2204.      *    LSHIFT+RSHIFT+RETURN is pressed. This routine will
  2205.      *    push a window on the stack.
  2206.      */
  2207.  
  2208. VOID
  2209. PushWindow(struct Window *Window)
  2210. {
  2211.     if(WindowStackPtr < 5)
  2212.     {
  2213.         WindowStack[WindowStackPtr++] = Window;
  2214.  
  2215.         TopWindow = Window;
  2216.     }
  2217. }
  2218.  
  2219.     /* PopWindow():
  2220.      *
  2221.      *    Remove topmost window from window stack.
  2222.      */
  2223.  
  2224. VOID
  2225. PopWindow()
  2226. {
  2227.     if(WindowStackPtr > 0)
  2228.     {
  2229.         WindowStackPtr--;
  2230.  
  2231.         if(WindowStackPtr)
  2232.             TopWindow = WindowStack[WindowStackPtr - 1];
  2233.         else
  2234.             TopWindow = Window;
  2235.     }
  2236. }
  2237.  
  2238.     /* SplitFileName():
  2239.      *
  2240.      *    Split a full file name into a file and a drawer name.
  2241.      */
  2242.  
  2243. VOID
  2244. SplitFileName(STRPTR FullName,STRPTR *FileName,STRPTR DrawerName)
  2245. {
  2246.     if(FilePart(FullName) == FullName)
  2247.     {
  2248.         *DrawerName    = 0;
  2249.         *FileName    = FullName;
  2250.     }
  2251.     else
  2252.     {
  2253.         STRPTR Dummy;
  2254.  
  2255.         strcpy(DrawerName,FullName);
  2256.  
  2257.         Dummy = PathPart(DrawerName);
  2258.  
  2259.         *Dummy = 0;
  2260.  
  2261.         *FileName = FilePart(FullName);
  2262.     }
  2263. }
  2264.  
  2265.     /* BackfillRoutine():
  2266.      *
  2267.      *    Window layer backfill routine.
  2268.      */
  2269.  
  2270. VOID SAVE_DS ASM
  2271. BackfillRoutine(REG(a0) struct Hook *UnusedHook,REG(a2) struct RastPort *RPort,REG(a1) LayerMsg *Bounds)
  2272. {
  2273.     struct RastPort RastPort;
  2274.  
  2275.     CopyMem(RPort,&RastPort,sizeof(struct RastPort));
  2276.     RastPort.Layer = NULL;
  2277.  
  2278.     RPort = &RastPort;
  2279.  
  2280.     SetAPen(RPort,Pens[BACKGROUNDPEN]);
  2281.     SetDrMd(RPort,JAM2);
  2282.  
  2283.     RectFill(RPort,Bounds->Bounds.MinX,Bounds->Bounds.MinY,Bounds->Bounds.MaxX,Bounds->Bounds.MaxY);
  2284. }
  2285.  
  2286. struct NameSegment
  2287. {
  2288.     UBYTE    String[63],
  2289.             Separator;
  2290. };
  2291.  
  2292. STATIC STRPTR
  2293. FindChar(STRPTR Template,LONG c)
  2294. {
  2295.     while(*Template)
  2296.     {
  2297.         if(*Template == c)
  2298.             return(Template);
  2299.         else
  2300.             Template++;
  2301.     }
  2302.  
  2303.     return(NULL);
  2304. }
  2305.  
  2306. STATIC UBYTE *
  2307. GetNameSegment(struct NameSegment *NameSegment,UBYTE *cp,LONG i)
  2308. {
  2309.     UBYTE *xp = NameSegment[i].String;
  2310.  
  2311.     while (*cp && !FindChar("._+-,@~=",*cp))
  2312.         *xp++ = *cp++;
  2313.  
  2314.     *xp = '\0';
  2315.  
  2316.     NameSegment[i].Separator = *cp;
  2317.  
  2318.     if (*cp)
  2319.         cp++;
  2320.  
  2321.     if(NameSegment[i].String[0] || NameSegment[i].Separator)
  2322.         return(cp);
  2323.     else
  2324.         return(NULL);
  2325. }
  2326.  
  2327. STATIC VOID
  2328. CopyNameSegment(struct NameSegment *NameSegment,UBYTE *Destination,LONG Zap)
  2329. {
  2330.     UBYTE *cp = Destination,*xp;
  2331.  
  2332.     for(xp = NameSegment[0].String ; *xp ; )
  2333.         *cp++ = *xp++;
  2334.  
  2335.     if(NameSegment[0].Separator)
  2336.     {
  2337.         LONG i;
  2338.  
  2339.         *cp++ = NameSegment[0].Separator;
  2340.  
  2341.         for(i = Zap + 1 ; ; i++)
  2342.         {
  2343.             for(xp = NameSegment[i].String ; *xp ; )
  2344.                 *cp++ = *xp++;
  2345.  
  2346.             if(NameSegment[i].Separator)
  2347.                 *cp++ = NameSegment[i].Separator;
  2348.             else
  2349.             {
  2350.                 if(!NameSegment[i].String[0])
  2351.                     break;
  2352.             }
  2353.         }
  2354.     }
  2355.  
  2356.     *cp = 0;
  2357. }
  2358.  
  2359.     /* ShrinkName():
  2360.      *
  2361.      *    Shrink a file name down to a number of characters, if
  2362.      *    possible preserving the structure of the name. Algorithm
  2363.      *    courtesy of the "shrink" program by Simon Brown,
  2364.      *    Edinburgh University.
  2365.      */
  2366.  
  2367. UBYTE *
  2368. ShrinkName(UBYTE *Source,UBYTE *Destination,LONG MaxLength,BOOL FixSuffix)
  2369. {
  2370.     #define MAXSEGS 10
  2371.  
  2372.     struct NameSegment NameSegment[MAXSEGS];
  2373.  
  2374.     LONG i,NumSegments,SuffixLength,Remainder,Delete,Total,Zap = 0;
  2375.     UBYTE *OldPtr = (UBYTE *)Source;
  2376.  
  2377.     for(i = 0 ; i < MAXSEGS && (OldPtr = GetNameSegment(NameSegment,OldPtr,i)) ; i++);
  2378.  
  2379.     if(i < MAXSEGS)
  2380.     {
  2381.         NumSegments = i - 1;
  2382.  
  2383.         if((NumSegments * 2) < MaxLength)
  2384.         {
  2385.             SuffixLength = strlen(NameSegment[NumSegments].String);
  2386.  
  2387.             if(SuffixLength > MaxLength - NumSegments - 1)
  2388.             {
  2389.                 SuffixLength = MaxLength - (2 * NumSegments) - 1;
  2390.  
  2391.                 NameSegment[NumSegments].String[SuffixLength - 1] = 0;
  2392.             }
  2393.             else
  2394.             {
  2395.                 if (SuffixLength + NumSegments > MaxLength-NumSegments-1)
  2396.                     Zap = NumSegments - (MaxLength-SuffixLength)/2;
  2397.             }
  2398.  
  2399.             if(NumSegments >= 1)
  2400.             {
  2401.                 for(i = Zap + 1 ; i <= NumSegments ; i++)
  2402.                 {
  2403.                     if(NameSegment[i].Separator)
  2404.                         SuffixLength++;
  2405.                 }
  2406.  
  2407.                 if(NameSegment[0].Separator)
  2408.                     SuffixLength++;
  2409.  
  2410.                 Remainder = MaxLength - SuffixLength;
  2411.  
  2412.                 Delete = Remainder / NumSegments;
  2413.  
  2414.                 Total = SuffixLength;
  2415.  
  2416.                 for(i = Zap + 1 ; i < NumSegments ; i++)
  2417.                 {
  2418.                     NameSegment[i].String[Delete] = 0;
  2419.  
  2420.                     Total += Delete;
  2421.                 }
  2422.  
  2423.                 NameSegment[0].String[MaxLength - Total] = 0;
  2424.             }
  2425.  
  2426.             CopyNameSegment(NameSegment,Destination,Zap);
  2427.         }
  2428.         else
  2429.             strcpy(Destination,Source);
  2430.     }
  2431.     else
  2432.         strcpy(Destination,Source);
  2433.  
  2434.     if(FixSuffix)
  2435.     {
  2436.         BOOL    GotDot    = FALSE;
  2437.         LONG    Len    = strlen(Destination),Dots;
  2438.  
  2439.         for(i = Dots = 0 ; i < Len ; i++)
  2440.         {
  2441.             if(Destination[i] == '.')
  2442.                 Dots++;
  2443.         }
  2444.  
  2445.         if(!Dots)
  2446.         {
  2447.             if(Len < 4)
  2448.                 strcat(Destination,".___");
  2449.             else
  2450.                 Destination[Len - 4] = '.';
  2451.         }
  2452.  
  2453.         for(i = Len - 1 ; i >= 0 ; i--)
  2454.         {
  2455.             if(Destination[i] == '.')
  2456.             {
  2457.                 if(GotDot)
  2458.                     Destination[i] = '_';
  2459.                 else
  2460.                     GotDot = TRUE;
  2461.             }
  2462.  
  2463.             if(Destination[i] == '\\')
  2464.                 Destination[i] = '-';
  2465.         }
  2466.     }
  2467.  
  2468.     return(Destination);
  2469. }
  2470.  
  2471.     /* BuildFontName(STRPTR Destination,STRPTR Name,LONG Size):
  2472.      *
  2473.      *    Build a font name and size string from given
  2474.      *    information (raw name and size).
  2475.      */
  2476.  
  2477. VOID
  2478. BuildFontName(STRPTR Destination,LONG DestinationSize,STRPTR Name,LONG Size)
  2479. {
  2480.     UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  2481.     LONG Len;
  2482.  
  2483.     Name    = FilePart(Name);
  2484.     Len        = strlen(Name);
  2485.  
  2486.     if(Len > 5 && !Stricmp(&Name[Len - 5],".font"))
  2487.     {
  2488.         strcpy(LocalBuffer,Name);
  2489.  
  2490.         LocalBuffer[Len - 5] = 0;
  2491.  
  2492.         Name = LocalBuffer;
  2493.     }
  2494.  
  2495.     LimitedSPrintf(DestinationSize,Destination,"%s %ld",Name,Size);
  2496. }
  2497.  
  2498.     /* FixName(STRPTR Name):
  2499.      *
  2500.      *    Build a correct AmigaDOS filename.
  2501.      */
  2502.  
  2503. VOID
  2504. FixName(STRPTR Name)
  2505. {
  2506.     LONG NameLen = strlen(Name),i;
  2507.  
  2508.         /* Replace special characters. */
  2509.  
  2510.     for(i = 0 ; i < NameLen ; i++)
  2511.     {
  2512.         switch(Name[i])
  2513.         {
  2514.             case ' ':
  2515.  
  2516.                 Name[i] = '_';
  2517.                 break;
  2518.  
  2519.             case ':':
  2520.  
  2521.                 Name[i] = '.';
  2522.                 break;
  2523.  
  2524.             case '/':
  2525.  
  2526.                 Name[i] = '\\';
  2527.                 break;
  2528.  
  2529.             case '\"':
  2530.  
  2531.                 Name[i] = '\'';
  2532.                 break;
  2533.         }
  2534.     }
  2535.  
  2536.         /* Truncate the name. */
  2537.  
  2538.     if(NameLen > 31)
  2539.         Name[31] = 0;
  2540. }
  2541.  
  2542.     /* ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String):
  2543.      *
  2544.      *    Display an error message, in human readable form if possible.
  2545.      */
  2546.  
  2547. VOID
  2548. ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String)
  2549. {
  2550.     STATIC LONG LocalErrors[][2] =
  2551.     {
  2552.         ERR_SAVE_ERROR,            MSG_ERR_COULD_NOT_SAVE_FILE_TXT,
  2553.         ERR_LOAD_ERROR,            MSG_ERR_COULD_NOT_LOAD_FILE_TXT,
  2554.         ERR_OUTDATED,            MSG_ERR_OUTDATED_TXT,
  2555.         ERR_EXECUTE_ERROR,        MSG_ERR_COULD_NOT_EXECUTE_PROGRAM_TXT,
  2556.  
  2557.         ERR_FILE_NOT_FOUND,        MSG_VERIFY_NO_FILE_TXT,
  2558.         ERR_DRAWER_NOT_FOUND,    MSG_VERIFY_DRAWER_NOT_FOUND_TXT,
  2559.         ERR_PROGRAM_NOT_FOUND,    MSG_VERIFY_NO_PROGRAM_TXT,
  2560.         ERR_NOT_A_FILE,            MSG_VERIFY_DRAWER_NOT_A_FILE_TXT,
  2561.         ERR_NOT_A_DRAWER,        MSG_VERIFY_FILE_NOT_A_DRAWER_TXT,
  2562.  
  2563.         IFFERR_NOMEM,            MSG_IFFERR_NOMEM_TXT,
  2564.         IFFERR_READ,            MSG_IFFERR_READ_TXT,
  2565.         IFFERR_WRITE,            MSG_IFFERR_WRITE_TXT,
  2566.         IFFERR_SEEK,            MSG_IFFERR_SEEK_TXT,
  2567.         IFFERR_MANGLED,            MSG_IFFERR_MANGLED_TXT,
  2568.         IFFERR_NOTIFF,            MSG_IFFERR_NOTIFF_TXT,
  2569.  
  2570.         0
  2571.     };
  2572.  
  2573.     UBYTE LocalBuffer1[FAULT_MAX],LocalBuffer2[FAULT_MAX];
  2574.     STRPTR PrimaryError,SecondaryError;
  2575.  
  2576.     PrimaryError = SecondaryError = NULL;
  2577.  
  2578.     if(Primary)
  2579.     {
  2580.         LONG i;
  2581.  
  2582.         for(i = 0 ; LocalErrors[i][0] ; i++)
  2583.         {
  2584.             if(LocalErrors[i][0] == Primary)
  2585.             {
  2586.                 PrimaryError = LocaleString(LocalErrors[i][1]);
  2587.  
  2588.                 break;
  2589.             }
  2590.         }
  2591.  
  2592.         if(!PrimaryError)
  2593.         {
  2594.             if(Fault(Primary,NULL,LocalBuffer1,sizeof(LocalBuffer1)))
  2595.                 PrimaryError = LocalBuffer1;
  2596.         }
  2597.     }
  2598.  
  2599.     if(Secondary)
  2600.     {
  2601.         LONG i;
  2602.  
  2603.         for(i = 0 ; LocalErrors[i][0] ; i++)
  2604.         {
  2605.             if(LocalErrors[i][0] == Secondary)
  2606.             {
  2607.                 SecondaryError = LocaleString(LocalErrors[i][1]);
  2608.  
  2609.                 break;
  2610.             }
  2611.         }
  2612.  
  2613.         if(!SecondaryError)
  2614.         {
  2615.             if(Fault(Secondary,NULL,LocalBuffer2,sizeof(LocalBuffer2)))
  2616.                 SecondaryError = LocalBuffer2;
  2617.         }
  2618.     }
  2619.  
  2620.     if(PrimaryError)
  2621.     {
  2622.         if(String)
  2623.             ShowRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),String,SecondaryError);
  2624.         else
  2625.             ShowRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),SecondaryError);
  2626.     }
  2627. }
  2628.  
  2629. struct List *
  2630. BuildModeList(LONG *Index,ULONG DisplayMode,MODEFILTER ModeFilter,APTR UserData)
  2631. {
  2632.     struct List    *List;
  2633.     LONG         Count = 0;
  2634.  
  2635.     *Index = 0;
  2636.  
  2637.     if(List = CreateList())
  2638.     {
  2639.         struct DisplayInfo    DisplayInfo;
  2640.         ULONG                SomeMode = INVALID_ID;
  2641.  
  2642.         while((SomeMode = NextDisplayInfo(SomeMode)) != INVALID_ID)
  2643.         {
  2644.             if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,SomeMode))
  2645.             {
  2646.                 if((DisplayInfo.PropertyFlags & DIPF_IS_WB) && !(DisplayInfo.NotAvailable & ~DI_AVAIL_NOTWITHGENLOCK))
  2647.                 {
  2648.                     UBYTE ModeNameBuffer[DISPLAYNAMELEN + 1];
  2649.                     struct ModeNode    *ModeNode;
  2650.  
  2651.                     if(ModeFilter)
  2652.                     {
  2653.                         if(!(*ModeFilter)(SomeMode,UserData))
  2654.                             continue;
  2655.                     }
  2656.  
  2657.                     GetModeName(SomeMode,ModeNameBuffer,sizeof(ModeNameBuffer));
  2658.  
  2659.                     if(ModeNode = (struct ModeNode *)AllocVecPooled(sizeof(struct ModeNode) + strlen(ModeNameBuffer) + 1,MEMF_ANY))
  2660.                     {
  2661.                         strcpy(ModeNode->Node.ln_Name = (STRPTR)(ModeNode + 1),ModeNameBuffer);
  2662.  
  2663.                         ModeNode->DisplayID = SomeMode;
  2664.  
  2665.                         AddTail(List,(struct Node *)ModeNode);
  2666.  
  2667.                         Count++;
  2668.                     }
  2669.                 }
  2670.             }
  2671.         }
  2672.     }
  2673.  
  2674.     if(Count)
  2675.     {
  2676.         struct ModeNode    *Node,*Next;
  2677.  
  2678.         for(Node = (struct ModeNode *)List->lh_Head ; Node->Node.ln_Succ ; Node = (struct ModeNode *)Node->Node.ln_Succ)
  2679.         {
  2680.             if(!(Node->DisplayID & MONITOR_ID_MASK))
  2681.             {
  2682.                 for(Next = (struct ModeNode *)List->lh_Head ; Next->Node.ln_Succ ; Next = (struct ModeNode *)Next->Node.ln_Succ)
  2683.                 {
  2684.                     if((Node->DisplayID & ~MONITOR_ID_MASK) == (Next->DisplayID & ~MONITOR_ID_MASK) && Next != Node)
  2685.                         Node->DisplayID = INVALID_ID;
  2686.                 }
  2687.             }
  2688.  
  2689.             for(Next = (struct ModeNode *)List->lh_Head ; Next->Node.ln_Succ ; Next = (struct ModeNode *)Next->Node.ln_Succ)
  2690.             {
  2691.                 if(Node->DisplayID == Next->DisplayID && Next != Node)
  2692.                     Next->DisplayID = INVALID_ID;
  2693.             }
  2694.         }
  2695.  
  2696.         for(Node = (struct ModeNode *)List->lh_Head ; Next = (struct ModeNode *)Node->Node.ln_Succ ; Node = Next)
  2697.         {
  2698.             if(Node->DisplayID == INVALID_ID)
  2699.             {
  2700.                 Count--;
  2701.  
  2702.                 Remove((struct Node *)Node);
  2703.  
  2704.                 FreeVecPooled(Node);
  2705.             }
  2706.         }
  2707.     }
  2708.  
  2709.     if(Count)
  2710.     {
  2711.         struct ModeNode    *Node,*Next;
  2712.  
  2713.         for(Count = 0, Node = (struct ModeNode *)List->lh_Head ; Next = (struct ModeNode *)Node->Node.ln_Succ ; Node = Next)
  2714.         {
  2715.             if(Node->DisplayID == DisplayMode)
  2716.             {
  2717.                 *Index = Count;
  2718.  
  2719.                 break;
  2720.             }
  2721.         }
  2722.  
  2723.         return(List);
  2724.     }
  2725.     else
  2726.     {
  2727.         DeleteList(List);
  2728.  
  2729.         return(NULL);
  2730.     }
  2731. }
  2732.  
  2733.     /* IsAssign(STRPTR Name):
  2734.      *
  2735.      *    Does a name refer to an assignment?
  2736.      */
  2737.  
  2738. BOOL
  2739. IsAssign(STRPTR Name)
  2740. {
  2741.     LONG NameLen    = strlen(Name) - 1;
  2742.     BOOL Result        = FALSE;
  2743.  
  2744.         /* Does it end with a colon? */
  2745.  
  2746.     if(Name[NameLen] == ':')
  2747.     {
  2748.         struct DosList *DosList;
  2749.         STRPTR AssignName;
  2750.  
  2751.             /* Lock the list of assignments for reading. */
  2752.  
  2753.         DosList = LockDosList(LDF_ASSIGNS | LDF_READ);
  2754.  
  2755.             /* Scan the list... */
  2756.  
  2757.         while(DosList = NextDosEntry(DosList,LDF_ASSIGNS))
  2758.         {
  2759.                 /* Convert the name from icky
  2760.                  * BCPL to `C' style string.
  2761.                  */
  2762.  
  2763.             AssignName = (STRPTR)BADDR(DosList->dol_Name);
  2764.  
  2765.                 /* Does the name length match? */
  2766.  
  2767.             if(AssignName[0] == NameLen)
  2768.             {
  2769.                     /* Does the name itself match? */
  2770.  
  2771.                 if(!Strnicmp(&AssignName[1],Name,NameLen))
  2772.                 {
  2773.                     Result = TRUE;
  2774.  
  2775.                     break;
  2776.                 }
  2777.             }
  2778.         }
  2779.  
  2780.             /* Unlock the list of assignments. */
  2781.  
  2782.         UnLockDosList(LDF_ASSIGNS | LDF_READ);
  2783.     }
  2784.  
  2785.         /* Return the result. */
  2786.  
  2787.     return(Result);
  2788. }
  2789.  
  2790.     /* LockInAssign(BPTR TheLock,STRPTR TheAssignment):
  2791.      *
  2792.      *    Check if a file lock is part of an assignment.
  2793.      */
  2794.  
  2795. BOOL
  2796. LockInAssign(BPTR TheLock,STRPTR TheAssignment)
  2797. {
  2798.     struct DevProc    *DevProc        = NULL;
  2799.     struct MsgPort    *FileSysTask    = GetFileSysTask();
  2800.     BOOL             Result            = FALSE;
  2801.  
  2802.  
  2803.         /* Loop until all assignments are
  2804.          * processed.
  2805.          */
  2806.  
  2807.     do
  2808.     {
  2809.             /* Get the default filesystem task
  2810.              * in case we stumble upon NULL
  2811.              * directory locks.
  2812.              */
  2813.  
  2814.         if(DevProc = GetDeviceProc(TheAssignment,DevProc))
  2815.         {
  2816.                 /* Set the default filesystem task. */
  2817.  
  2818.             SetFileSysTask(DevProc->dvp_Port);
  2819.  
  2820.                 /* Is the lock on the list? */
  2821.  
  2822.             if(SameLock(DevProc->dvp_Lock,TheLock) == LOCK_SAME)
  2823.                 Result = TRUE;
  2824.         }
  2825.         else
  2826.             break;
  2827.     }
  2828.     while(DevProc && (DevProc->dvp_Flags & DVPF_ASSIGN) && !Result);
  2829.  
  2830.         /* Reset the default filesystem task. */
  2831.  
  2832.     SetFileSysTask(FileSysTask);
  2833.  
  2834.         /* Free device process data. */
  2835.  
  2836.     if(DevProc)
  2837.         FreeDeviceProc(DevProc);
  2838.  
  2839.     return(Result);
  2840. }
  2841.  
  2842.     /* DeleteBitMap(struct BitMap *BitMap):
  2843.      *
  2844.      *    Delete a bitmap created by CreateBitMap().
  2845.      */
  2846.  
  2847. VOID
  2848. DeleteBitMap(struct BitMap *BitMap)
  2849. {
  2850.     if(BitMap)
  2851.     {
  2852.         WaitBlit();
  2853.  
  2854.         if(Kick30)
  2855.             FreeBitMap(BitMap);
  2856.         else
  2857.         {
  2858.             LONG i,*Sizes,Width,Height;
  2859.  
  2860.             Sizes = &((LONG *)BitMap)[-2];
  2861.  
  2862.             Width = Sizes[0];
  2863.             Height = Sizes[1];
  2864.  
  2865.             for(i = 0 ; i < BitMap->Depth ; i++)
  2866.                 FreeRaster(BitMap->Planes[i],Width,Height);
  2867.  
  2868.             FreeVecPooled(Sizes);
  2869.         }
  2870.     }
  2871. }
  2872.  
  2873.     /* CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend):
  2874.      *
  2875.      *    Create a new bitmap with given properties.
  2876.      */
  2877.  
  2878. struct BitMap *
  2879. CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend)
  2880. {
  2881.     if(Kick30)
  2882.         return(AllocBitMap(Width,Height,Depth,Flags,Friend));
  2883.     else
  2884.     {
  2885.         struct BitMap    *BitMap;
  2886.         LONG             Plus;
  2887.         LONG            *Sizes;
  2888.  
  2889.         if(Depth > 8)
  2890.             Plus = (Depth - 8) * sizeof(PLANEPTR);
  2891.         else
  2892.             Plus = 0;
  2893.  
  2894.         if(!(Sizes = (LONG *)AllocVecPooled(sizeof(LONG) * 2 + sizeof(struct BitMap) + Plus,MEMF_CLEAR)))
  2895.             BitMap = NULL;
  2896.         else
  2897.         {
  2898.             LONG i;
  2899.  
  2900.             BitMap = (struct BitMap *)&Sizes[2];
  2901.  
  2902.             InitBitMap(BitMap,Depth,Width,Height);
  2903.  
  2904.             for(i = 0 ; i < BitMap->Depth ; i++)
  2905.             {
  2906.                 if(!(BitMap->Planes[i] = AllocRaster(Width,Height)))
  2907.                 {
  2908.                     LONG j;
  2909.  
  2910.                     for(j = 0 ; j < i ; j++)
  2911.                         FreeRaster(BitMap->Planes[j],Width,Height);
  2912.  
  2913.                     FreeVecPooled(Sizes);
  2914.  
  2915.                     return(NULL);
  2916.                 }
  2917.             }
  2918.  
  2919.             if(Flags & BMF_CLEAR)
  2920.                 BltBitMap(BitMap,0,0,BitMap,0,0,Width,Height,0x00,(1 << Depth) - 1,NULL);
  2921.  
  2922.             Sizes[0] = Width;
  2923.             Sizes[1] = Height;
  2924.         }
  2925.  
  2926.         return(BitMap);
  2927.     }
  2928. }
  2929.  
  2930.     /* LaunchWorkCommon(LaunchMsg *Startup,BOOL Synchronous):
  2931.      *
  2932.      *    Does the final launch & cleanup work with the
  2933.      *    startup packed provided.
  2934.      */
  2935.  
  2936. STATIC BOOL
  2937. LaunchWorkCommon(LaunchMsg *Startup,BOOL Synchronous)
  2938. {
  2939.         /* Did we succeed in creating the startup message? */
  2940.  
  2941.     if(Startup)
  2942.     {
  2943.         LONG Result;
  2944.  
  2945.             /* Launch the program. */
  2946.  
  2947.         Result = LaunchSomething(Config->MiscConfig->SuppressOutput ? (STRPTR)"NIL:" : Config->MiscConfig->WindowName,Synchronous,Startup);
  2948.  
  2949.             /* And return the result. */
  2950.  
  2951.         return((BOOL)(Result == 0));
  2952.     }
  2953.     else
  2954.         return(FALSE);
  2955. }
  2956.  
  2957.     /* RexxLaunchCleanup(LaunchMsg *Startup):
  2958.      *
  2959.      *    Displays an error message for the ARexx script
  2960.      *    to be launched.
  2961.      */
  2962.  
  2963. STATIC VOID
  2964. LaunchRexxCleanup(LaunchMsg *Startup)
  2965. {
  2966.     if(Startup->Result != 0)
  2967.         Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Startup->Command,Startup->Result,Startup->Result2);
  2968. }
  2969.  
  2970.     /* LaunchRexxCommon(STRPTR Command):
  2971.      *
  2972.      *    Launch an ARexx command. This routine is always
  2973.      *    asynchronous.
  2974.      */
  2975.  
  2976. BOOL
  2977. LaunchRexxAsync(STRPTR Command)
  2978. {
  2979.     LaunchMsg *Startup;
  2980.  
  2981.         /* Skip leading blanks. */
  2982.  
  2983.     while(*Command == ' ' || *Command == '\t')
  2984.         Command++;
  2985.  
  2986.         /* Create the launch startup message. This will copy the
  2987.          * command string.
  2988.          */
  2989.  
  2990.     Startup = CreateRexxCmdLaunchMsg(Command,NULL,LaunchRexxCleanup);
  2991.  
  2992.         /* Do the work. */
  2993.  
  2994.     return((BOOL)(LaunchWorkCommon(Startup,FALSE)));
  2995. }
  2996.  
  2997.     /* LaunchCommandCommon(STRPTR Command, BOOL Synchronous):
  2998.      *
  2999.      *    Launch a command, try to figure out if it's an ARexx
  3000.      *    command, a plain batch file or a program and act
  3001.      *    accordingly.
  3002.      */
  3003.  
  3004. STATIC BOOL
  3005. LaunchCommandCommon(STRPTR Command, BOOL Synchronous)
  3006. {
  3007.     STRPTR         OriginalCommand;
  3008.     UBYTE         NameBuffer[MAX_FILENAME_LENGTH];
  3009.     BOOL         IsScript;
  3010.     BPTR         CommandFile;
  3011.     BPTR         FileLock;
  3012.     LONG         i;
  3013.     LaunchMsg    *Startup;
  3014.  
  3015.         /* Chop off the arguments. */
  3016.  
  3017.     while(*Command == ' ' || *Command == '\t')
  3018.         Command++;
  3019.  
  3020.     OriginalCommand = Command;
  3021.  
  3022.     CopyMem(Command,NameBuffer,sizeof(NameBuffer) - 1);
  3023.  
  3024.     NameBuffer[sizeof(NameBuffer) - 1] = 0;
  3025.  
  3026.     for(i = 0 ; i < sizeof(NameBuffer) ; i++)
  3027.     {
  3028.         if(NameBuffer[i] == ' ' || NameBuffer[i] == '\t')
  3029.         {
  3030.             NameBuffer[i] = 0;
  3031.             break;
  3032.         }
  3033.     }
  3034.  
  3035.         /* Now do something useful. Check if the command
  3036.          * could be an ARexx script.
  3037.          */
  3038.  
  3039.     if(CommandFile = Open(NameBuffer,MODE_OLDFILE))
  3040.     {
  3041.         UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  3042.         BOOL IsRexx = FALSE;
  3043.         LONG Len;
  3044.  
  3045.             /* 256 bytes may be not be enough, but then
  3046.              * we're only guessing.
  3047.              */
  3048.  
  3049.         if((Len = Read(CommandFile,LocalBuffer,sizeof(LocalBuffer))) > 0)
  3050.         {
  3051.             UBYTE c;
  3052.  
  3053.             for(i = 0 ; i < Len - 1 ; i++)
  3054.             {
  3055.                 c = LocalBuffer[i];
  3056.  
  3057.                     /* Stop on invalid characters. */
  3058.  
  3059.                 if((c < ' ' && c != '\r' && c != '\n' && c != '\a') || (c >= 127 && c < 160))
  3060.                     break;
  3061.                 else
  3062.                 {
  3063.                         /* Looks like the typical
  3064.                          * introductory comment line.
  3065.                          */
  3066.  
  3067.                     if(c == '/' && LocalBuffer[i + 1] == '*')
  3068.                     {
  3069.                         IsRexx = TRUE;
  3070.                         break;
  3071.                     }
  3072.                 }
  3073.             }
  3074.         }
  3075.  
  3076.         Close(CommandFile);
  3077.  
  3078.             /* If it's a Rexx script, launch it. */
  3079.  
  3080.         if(IsRexx)
  3081.             return(LaunchRexxAsync(Command));
  3082.     }
  3083.  
  3084.         /* Ok, second check. Does it have the script bit set? */
  3085.  
  3086.     IsScript = FALSE;
  3087.  
  3088.     if(FileLock = Lock(NameBuffer,ACCESS_READ))
  3089.     {
  3090.         D_S(struct FileInfoBlock,FileInfo);
  3091.  
  3092.         if(Examine(FileLock,FileInfo))
  3093.         {
  3094.             if(FileInfo->fib_Protection & FIBF_SCRIPT)
  3095.                 IsScript = TRUE;
  3096.         }
  3097.  
  3098.         UnLock(FileLock);
  3099.     }
  3100.  
  3101.         /* If it's a script command, prepend the "Execute " command. */
  3102.  
  3103.     if(IsScript)
  3104.     {
  3105.             /* Make room for the new command. */
  3106.  
  3107.         if(!(Command = AllocVecPooled(strlen("Execute ") + strlen(OriginalCommand) + 1,MEMF_ANY)))
  3108.             return(FALSE);
  3109.         else
  3110.         {
  3111.             strcpy(Command,"Execute ");
  3112.             strcat(Command,OriginalCommand);
  3113.         }
  3114.     }
  3115.  
  3116.         /* Create the launch startup message. This will copy the
  3117.          * command string.
  3118.          */
  3119.  
  3120.     Startup = CreateProgramLaunchMsg(Command,NULL);
  3121.  
  3122.         /* If we had to make a copy of the command name, release the memory. */
  3123.  
  3124.     if(Command != OriginalCommand)
  3125.         FreeVecPooled(Command);
  3126.  
  3127.         /* Do the work. */
  3128.  
  3129.     return((BOOL)(LaunchWorkCommon(Startup,Synchronous)));
  3130. }
  3131.  
  3132.     /* LaunchCommand(STRPTR Command):
  3133.      *
  3134.      *    Launches a command, synchronous version.
  3135.      */
  3136.  
  3137. BOOL
  3138. LaunchCommand(STRPTR Command)
  3139. {
  3140.     return(LaunchCommandCommon(Command,TRUE));
  3141. }
  3142.  
  3143.     /* LaunchCommandAsync(STRPTR Command):
  3144.      *
  3145.      *    Launches a command, asynchronous version.
  3146.      */
  3147.  
  3148. BOOL
  3149. LaunchCommandAsync(STRPTR Command)
  3150. {
  3151.     return(LaunchCommandCommon(Command,FALSE));
  3152. }
  3153.  
  3154.     /* LaunchProcess(STRPTR Name,VOID (*Entry)(VOID),BPTR Stream):
  3155.      *
  3156.      *    Launch a new process from given entry point, with given
  3157.      *    name and I/O stream.
  3158.      */
  3159.  
  3160. struct Process *
  3161. LaunchProcess(STRPTR Name,VOID (*Entry)(VOID),BPTR Stream)
  3162. {
  3163.     struct MsgPort *ConsoleTask;
  3164.  
  3165.     if(Stream && GoodStream(Stream))
  3166.         ConsoleTask = ((struct FileHandle *)BADDR(Stream))->fh_Type;
  3167.     else
  3168.         ConsoleTask = NULL;
  3169.  
  3170.     return(CreateNewProcTags(
  3171.         NP_Entry,        Entry,
  3172.         NP_StackSize,    8000,
  3173.         NP_Name,        Name,
  3174.         NP_Cli,            TRUE,
  3175.         NP_ConsoleTask,    ConsoleTask,
  3176.  
  3177.         ConsoleTask ? TAG_IGNORE : TAG_DONE,0,
  3178.  
  3179.         NP_Output,    ConsoleTask ? NULL : Stream,
  3180.  
  3181.         ConsoleTask ? NP_Input : TAG_IGNORE,Stream,
  3182.     TAG_DONE));
  3183. }
  3184.  
  3185.     /* String2Boolean(STRPTR String):
  3186.      *
  3187.      *    Compare string contents with table contents,
  3188.      *    map the string to a boolean value.
  3189.      */
  3190.  
  3191. BOOL
  3192. String2Boolean(STRPTR String)
  3193. {
  3194.     STATIC STRPTR TrueOptions[] =
  3195.     {
  3196.         "ON",
  3197.         "TRUE",
  3198.         "T",
  3199.         "YES",
  3200.         "Y",
  3201.         "1"
  3202.     };
  3203.  
  3204.     LONG i;
  3205.  
  3206.     for(i = 0 ; i < NUM_ELEMENTS(TrueOptions) ; i++)
  3207.     {
  3208.         if(!Stricmp(String,TrueOptions[i]))
  3209.             return(TRUE);
  3210.     }
  3211.  
  3212.     return(FALSE);
  3213. }
  3214.  
  3215.     /* SendMessageGetReply(struct MsgPort *Port,struct Message *Message):
  3216.      *
  3217.      *    Send a message to a given MsgPort and wait for
  3218.      *    the reply.
  3219.      */
  3220.  
  3221. VOID
  3222. SendMessageGetReply(struct MsgPort *Port,struct Message *Message)
  3223. {
  3224.     struct MsgPort LocalPort;
  3225.     struct MsgPort *ReplyPort;
  3226.  
  3227.     ReplyPort = Message->mn_ReplyPort;
  3228.  
  3229.     InitSinglePort(&LocalPort);
  3230.  
  3231.     Message->mn_ReplyPort = &LocalPort;
  3232.  
  3233.     SetSignal(0,SIGF_SINGLE);
  3234.  
  3235.     PutMsg(Port,Message);
  3236.     WaitPort(&LocalPort);
  3237.     GetMsg(&LocalPort);
  3238.  
  3239.     Message->mn_ReplyPort = ReplyPort;
  3240. }
  3241.  
  3242.     /* SetOnlineState(BOOL IsOnline):
  3243.      *
  3244.      *    Set the current online state.
  3245.      */
  3246.  
  3247. VOID
  3248. SetOnlineState(BOOL IsOnline,LONG BackTime)
  3249. {
  3250.     ObtainSemaphore(&OnlineSemaphore);
  3251.  
  3252.     WasOnline    = Online;
  3253.     Online        = IsOnline;
  3254.  
  3255.     if(!WasOnline && Online)
  3256.     {
  3257.         GetSysTime(&OnlineTime);
  3258.         OnlineTime.tv_secs -= BackTime;
  3259.     }
  3260.  
  3261.     if(WasOnline && !Online)
  3262.         ActivateJob(MainJobQueue,OnlineCleanupJob);
  3263.  
  3264.     ReleaseSemaphore(&OnlineSemaphore);
  3265. }
  3266.  
  3267.     /* SwapMem(APTR FromPtr,APTR ToPtr,LONG Size):
  3268.      *
  3269.      *    Exchange the contents of two memory regions.
  3270.      */
  3271.  
  3272. VOID
  3273. SwapMem(APTR FromPtr,APTR ToPtr,LONG Size)
  3274. {
  3275.     UBYTE *From,*To,c;
  3276.  
  3277.     From    = FromPtr;
  3278.     To        = ToPtr;
  3279.  
  3280.     while(Size--)
  3281.     {
  3282.         c        = *From;
  3283.         *From++    = *To;
  3284.         *To++    = c;
  3285.     }
  3286. }
  3287.  
  3288.     /* CloseIFFClip(struct IFFHandle *Handle):
  3289.      *
  3290.      *    Closes the clipboard opened by OpenIFFClip.
  3291.      */
  3292.  
  3293. BOOL
  3294. CloseIFFClip(struct IFFHandle *Handle)
  3295. {
  3296.     if(Handle)
  3297.     {
  3298.         CloseIFF(Handle);
  3299.         CloseClipboard((struct ClipboardHandle *)Handle->iff_Stream);
  3300.         FreeIFF(Handle);
  3301.     }
  3302.  
  3303.     return(TRUE);
  3304. }
  3305.  
  3306.     /* OpenIFFClip(LONG Unit,LONG Mode):
  3307.      *
  3308.      *    Open the clipboard for reading or writing. This
  3309.      *    routine handles all the initizalizations and
  3310.      *    allocation and returns an IFFHandle ready
  3311.      *    to be used.
  3312.      */
  3313.  
  3314. struct IFFHandle *
  3315. OpenIFFClip(LONG Unit,LONG Mode)
  3316. {
  3317.     struct IFFHandle *Handle;
  3318.     LONG Error;
  3319.  
  3320.     if(Handle = AllocIFF())
  3321.     {
  3322.         if(Handle->iff_Stream = (ULONG)OpenClipboard(Unit))
  3323.         {
  3324.             InitIFFasClip(Handle);
  3325.  
  3326.             if(!(Error = OpenIFF(Handle,(Mode == MODE_NEWFILE) ? IFFF_WRITE : IFFF_READ)))
  3327.                 return(Handle);
  3328.  
  3329.             CloseClipboard((struct ClipboardHandle *)Handle->iff_Stream);
  3330.         }
  3331.         else
  3332.             Error = ERROR_NO_FREE_STORE;
  3333.  
  3334.         FreeIFF(Handle);
  3335.     }
  3336.     else
  3337.         Error = ERROR_NO_FREE_STORE;
  3338.  
  3339.     SetIoErr(Error);
  3340.  
  3341.     return(FALSE);
  3342. }
  3343.  
  3344.     /* CloseIFFStream(struct IFFHandle *Handle):
  3345.      *
  3346.      *    Closes an IFF file opened by OpenIFFStream.
  3347.      */
  3348.  
  3349. BOOL
  3350. CloseIFFStream(struct IFFHandle *Handle)
  3351. {
  3352.     if(Handle)
  3353.     {
  3354.         BOOL Result;
  3355.  
  3356.         CloseIFF(Handle);
  3357.         Result = Close(Handle->iff_Stream);
  3358.         FreeIFF(Handle);
  3359.  
  3360.         return(Result);
  3361.     }
  3362.     else
  3363.         return(TRUE);
  3364. }
  3365.  
  3366.     /* OpenIFFStream(STRPTR Name,LONG Mode):
  3367.      *
  3368.      *    Open an IFF file for reading or writing. This
  3369.      *    routine handles all the initizalizations and
  3370.      *    allocation and returns an IFFHandle ready
  3371.      *    to be used.
  3372.      */
  3373.  
  3374. struct IFFHandle *
  3375. OpenIFFStream(STRPTR Name,LONG Mode)
  3376. {
  3377.     struct IFFHandle *Handle;
  3378.     LONG Error;
  3379.  
  3380.     if(Handle = AllocIFF())
  3381.     {
  3382.         if(Handle->iff_Stream = Open(Name,Mode))
  3383.         {
  3384.             InitIFFasDOS(Handle);
  3385.  
  3386.             if(!(Error = OpenIFF(Handle,(Mode == MODE_NEWFILE) ? IFFF_WRITE : IFFF_READ)))
  3387.                 return(Handle);
  3388.  
  3389.             Close(Handle->iff_Stream);
  3390.  
  3391.             if(Mode == MODE_NEWFILE)
  3392.                 DeleteFile(Name);
  3393.         }
  3394.         else
  3395.             Error = IoErr();
  3396.  
  3397.         FreeIFF(Handle);
  3398.     }
  3399.     else
  3400.         Error = ERROR_NO_FREE_STORE;
  3401.  
  3402.     SetIoErr(Error);
  3403.  
  3404.     return(FALSE);
  3405. }
  3406.  
  3407.     /* InitHook(struct Hook *Hook,HOOKFUNC Func,APTR Data):
  3408.      *
  3409.      *    Set up a callback hook function.
  3410.      */
  3411.  
  3412. VOID
  3413. InitHook(struct Hook *Hook,HOOKFUNC Func,APTR Data)
  3414. {
  3415. #ifdef USE_GLUE
  3416.     Hook->h_Entry        = HookEntry;
  3417.     Hook->h_SubEntry    = Func;
  3418.     Hook->h_Data        = Data;
  3419. #else
  3420.     Hook->h_Entry        = Func;
  3421.     Hook->h_Data        = Data;
  3422. #endif    /* USE_GLUE */
  3423. }
  3424.  
  3425.     /* FitText(struct RastPort *RPort,UWORD Width,STRPTR String,LONG Len):
  3426.      *
  3427.      *    Check how many character fit into Width pixels.
  3428.      */
  3429.  
  3430. ULONG
  3431. FitText(struct RastPort *RPort,UWORD Width,STRPTR String,LONG Len)
  3432. {
  3433.     struct TextExtent Extent;
  3434.  
  3435.     if(Len == -1)
  3436.         Len = strlen(String);
  3437.  
  3438.     return(TextFit(RPort,String,Len,&Extent,NULL,1,Width,32767));
  3439. }
  3440.  
  3441.     /* DispatchRexxDialMsgList(BOOL Ok):
  3442.      *
  3443.      *    Dispatch all queued dial requests.
  3444.      */
  3445.  
  3446. VOID
  3447. DispatchRexxDialMsgList(BOOL Ok)
  3448. {
  3449.     struct RexxMsg *DialMsg;
  3450.     LONG Result;
  3451.  
  3452.     if(Ok)
  3453.         Result = RC_OK;
  3454.     else
  3455.         Result = RC_WARN;
  3456.  
  3457.     while(DialMsg = (struct RexxMsg *)RemHead(&RexxDialMsgList))
  3458.     {
  3459.         DialMsg->rm_Result1 = Result;
  3460.         DialMsg->rm_Result2 = 0;
  3461.  
  3462.         ReplyMsg((struct Message *)DialMsg);
  3463.     }
  3464. }
  3465.  
  3466.     /* CancelZModem():
  3467.      *
  3468.      *    Send the zmodem cancel sequence.
  3469.      */
  3470.  
  3471. VOID
  3472. CancelZModem()
  3473. {
  3474.     if(UsesZModem)
  3475.         DoSerialWrite(ZModemCancel,20);
  3476. }
  3477.  
  3478.     /* WaitForHandshake():
  3479.      *
  3480.      *    Clears the handshaking signal, then waits for it.
  3481.      *    Must be called while in Forbid().
  3482.      */
  3483.  
  3484. VOID
  3485. WaitForHandshake()
  3486. {
  3487.     SetSignal(0,SIG_HANDSHAKE);
  3488.     Wait(SIG_HANDSHAKE);
  3489. }
  3490.  
  3491.     /* ShakeHands(struct Task *Notify,ULONG NotifyMask):
  3492.      *
  3493.      *    Send a signal to a Task and wait for it to
  3494.      *    reply with the handshake signal.
  3495.      */
  3496.  
  3497. VOID
  3498. ShakeHands(struct Task *Notify,ULONG NotifyMask)
  3499. {
  3500.     if(Notify)
  3501.     {
  3502.         Forbid();
  3503.  
  3504.         Signal(Notify,NotifyMask);
  3505.  
  3506.         WaitForHandshake();
  3507.  
  3508.         Permit();
  3509.     }
  3510. }
  3511.  
  3512.     /* GetViewPortExtra(struct ViewPort *ViewPort):
  3513.      *
  3514.      *    Gets the extra information associated with a viewport.
  3515.      */
  3516.  
  3517. struct ViewPortExtra *
  3518. GetViewPortExtra(struct ViewPort *ViewPort)
  3519. {
  3520.     struct TagItem Tags[2] = { VTAG_VIEWPORTEXTRA_GET, NULL, TAG_DONE };
  3521.  
  3522.     if(!VideoControl(ViewPort->ColorMap,Tags))
  3523.         return((struct ViewPortExtra *)Tags[0].ti_Data);
  3524.     else
  3525.         return(NULL);
  3526. }
  3527.  
  3528.     /* OpenToAppend(STRPTR Name,BOOL *Created):
  3529.      *
  3530.      *    Open a plain AmigaDOS file to append data to it. If a new file
  3531.      *    is created this routine will indicate this by setting the
  3532.      *    boolean variable pointed to by "Created" to TRUE.
  3533.      */
  3534.  
  3535. BPTR
  3536. OpenToAppend(STRPTR Name,BOOL *Created)
  3537. {
  3538.     BPTR FileHandle;
  3539.     BPTR FileLock;
  3540.  
  3541.     if(FileLock = Lock(Name,EXCLUSIVE_LOCK))
  3542.     {
  3543.         if(!(FileHandle = OpenFromLock(FileLock)))
  3544.         {
  3545.             UnLock(FileLock);
  3546.  
  3547.             FileHandle = Open(Name,MODE_READWRITE);
  3548.         }
  3549.  
  3550.         if(FileHandle)
  3551.         {
  3552.             if(Seek(FileHandle,0,OFFSET_END) == -1)
  3553.             {
  3554.                 LONG Error;
  3555.  
  3556.                 Error = IoErr();
  3557.  
  3558.                 Close(FileHandle);
  3559.  
  3560.                 SetIoErr(Error);
  3561.  
  3562.                 return(NULL);
  3563.             }
  3564.         }
  3565.  
  3566.         if(Created)
  3567.             *Created = FALSE;
  3568.     }
  3569.     else
  3570.     {
  3571.         if(FileHandle = Open(Name,MODE_NEWFILE))
  3572.         {
  3573.             if(Created)
  3574.                 *Created = TRUE;
  3575.         }
  3576.     }
  3577.  
  3578.     return(FileHandle);
  3579. }
  3580.  
  3581.     /* PushStatus(WORD NewStatus):
  3582.      *
  3583.      *    Remember the current status and set the new one.
  3584.      */
  3585.  
  3586. VOID
  3587. PushStatus(WORD NewStatus)
  3588. {
  3589.     ObtainSemaphore(&StatusSemaphore);
  3590.  
  3591.     if(StatusStackPointer < 10)
  3592.         StatusStack[StatusStackPointer++] = NewStatus;
  3593.  
  3594.     ReleaseSemaphore(&StatusSemaphore);
  3595. }
  3596.  
  3597.     /* PopStatus():
  3598.      *
  3599.      *    Return to the old status value.
  3600.      */
  3601.  
  3602. VOID
  3603. PopStatus()
  3604. {
  3605.     ObtainSemaphore(&StatusSemaphore);
  3606.  
  3607.     if(StatusStackPointer > 0)
  3608.         StatusStackPointer--;
  3609.  
  3610.     ReleaseSemaphore(&StatusSemaphore);
  3611. }
  3612.  
  3613.     /* GetStatus():
  3614.      *
  3615.      *    Returns the current status.
  3616.      */
  3617.  
  3618. WORD
  3619. GetStatus()
  3620. {
  3621.     WORD Status;
  3622.  
  3623.     SafeObtainSemaphoreShared(&StatusSemaphore);
  3624.  
  3625.     if(StatusStackPointer > 0)
  3626.         Status = StatusStack[StatusStackPointer - 1];
  3627.     else
  3628.         Status = STATUS_READY;
  3629.  
  3630.     ReleaseSemaphore(&StatusSemaphore);
  3631.  
  3632.     if(Status == STATUS_READY && Get_xOFF())
  3633.         Status = STATUS_HOLDING;
  3634.  
  3635.     return(Status);
  3636. }
  3637.  
  3638.     /* Clear_xOFF():
  3639.      *
  3640.      *    Clears the xOFF stop marker.
  3641.      */
  3642.  
  3643. VOID
  3644. Clear_xOFF()
  3645. {
  3646.     ObtainSemaphore(&xONxOFF_Semaphore);
  3647.  
  3648.     xOFF_Enabled = FALSE;
  3649.  
  3650.     UpdateSerialJob();
  3651.  
  3652.     ReleaseSemaphore(&xONxOFF_Semaphore);
  3653. }
  3654.  
  3655.     /* Set_xOFF():
  3656.      *
  3657.      *    Sets the xOFF stop marker unless access to the
  3658.      *    marker is forbidden.
  3659.      */
  3660.  
  3661. VOID
  3662. Set_xOFF()
  3663. {
  3664.     ObtainSemaphore(&xONxOFF_Semaphore);
  3665.  
  3666.     if(xONxOFF_Lock == 0)
  3667.         xOFF_Enabled = TRUE;
  3668.  
  3669.     UpdateSerialJob();
  3670.  
  3671.     ReleaseSemaphore(&xONxOFF_Semaphore);
  3672. }
  3673.  
  3674.     /* Get_xOFF():
  3675.      *
  3676.      *    Queries the current state of the xOFF marker.
  3677.      */
  3678.  
  3679. BOOL
  3680. Get_xOFF()
  3681. {
  3682.     BOOL Result;
  3683.  
  3684.     SafeObtainSemaphoreShared(&xONxOFF_Semaphore);
  3685.  
  3686.     Result = xOFF_Enabled;
  3687.  
  3688.     ReleaseSemaphore(&xONxOFF_Semaphore);
  3689.  
  3690.     return(Result);
  3691. }
  3692.  
  3693.     /* Lock_xOFF():
  3694.      *
  3695.      *    Locks the current xOFF marker state.
  3696.      */
  3697.  
  3698. VOID
  3699. Lock_xOFF()
  3700. {
  3701.     ObtainSemaphore(&xONxOFF_Semaphore);
  3702.  
  3703.     xONxOFF_Lock++;
  3704.  
  3705.     ReleaseSemaphore(&xONxOFF_Semaphore);
  3706. }
  3707.  
  3708.     /* Unlock_xOFF():
  3709.      *
  3710.      *    Unlocks the current xOFF marker state.
  3711.      */
  3712.  
  3713. VOID
  3714. Unlock_xOFF()
  3715. {
  3716.     ObtainSemaphore(&xONxOFF_Semaphore);
  3717.  
  3718.     if(xONxOFF_Lock > 0)
  3719.         xONxOFF_Lock--;
  3720.  
  3721.     ReleaseSemaphore(&xONxOFF_Semaphore);
  3722. }
  3723.  
  3724.     /* MoveListViewNode():
  3725.      *
  3726.      *    Move the node of a list view somewhere.
  3727.      */
  3728.  
  3729. VOID
  3730. MoveListViewNode(LayoutHandle *Handle,struct List *List,LONG ListID,struct Node *Node,LONG *Offset,LONG How)
  3731. {
  3732.     LT_SetAttributes(Handle,ListID,
  3733.         GTLV_Labels,    ~0,
  3734.     TAG_DONE);
  3735.  
  3736.     MoveNode(List,Node,How);
  3737.  
  3738.     *Offset = GetNodeOffset(Node,List);
  3739.  
  3740.     LT_SetAttributes(Handle,ListID,
  3741.         GTLV_Labels,    List,
  3742.         LALV_Selected,    *Offset,
  3743.     TAG_DONE);
  3744. }
  3745.  
  3746.     /* StartProcessWaitForHandshake():
  3747.      *
  3748.      *    Create a new process and wait for the handshake
  3749.      *    signal.
  3750.      */
  3751.  
  3752. struct Process *
  3753. StartProcessWaitForHandshake(STRPTR Name,TASKENTRY Entry,...)
  3754. {
  3755.     struct Process *Process;
  3756.     va_list Args;
  3757.  
  3758.     va_start(Args,Entry);
  3759.  
  3760.     Forbid();
  3761.  
  3762.     if(Process = CreateNewProcTags(
  3763.         NP_Name,    Name,
  3764.         NP_Entry,    Entry,
  3765.     TAG_MORE,Args))
  3766.         WaitForHandshake();
  3767.  
  3768.     Permit();
  3769.  
  3770.     va_end(Args);
  3771.  
  3772.     return(Process);
  3773. }
  3774.  
  3775.     /* LocalGetCurrentDirName(STRPTR Buffer,LONG BufferSize):
  3776.      *
  3777.      *    Obtains the name of the "current" directory of the
  3778.      *    calling process, regardless of the current directory
  3779.      *    of the Shell environment the process may be running in.
  3780.      */
  3781.  
  3782. BOOL
  3783. LocalGetCurrentDirName(STRPTR Buffer,LONG BufferSize)
  3784. {
  3785.     return((BOOL)NameFromLock(((struct Process *)FindTask(NULL))->pr_CurrentDir,Buffer,BufferSize));
  3786. }
  3787.  
  3788.     /* SafeObtainSemaphoreShared():
  3789.      *
  3790.      *    This is for backwards compatibility with Kickstart 2.04 and
  3791.      *    avoids a deadlock when trying to get a shared lock on
  3792.      *    a semaphore already held in exclusive mode by the same Task.
  3793.      */
  3794.  
  3795. VOID
  3796. SafeObtainSemaphoreShared(struct SignalSemaphore *Semaphore)
  3797. {
  3798.         /* Do it right with Kickstart 3.x. */
  3799.  
  3800.     if(Kick30)
  3801.         ObtainSemaphoreShared(Semaphore);
  3802.     else
  3803.     {
  3804.             /* Try to get the shared semaphore */
  3805.  
  3806.         if(!AttemptSemaphoreShared(Semaphore))
  3807.         {
  3808.                 /* Check if we can get the exclusive version */
  3809.  
  3810.             if(!AttemptSemaphore(Semaphore))
  3811.             {
  3812.                     /* Oh well, wait for the shared lock */
  3813.  
  3814.                 ObtainSemaphoreShared(Semaphore);
  3815.             }
  3816.         }
  3817.     }
  3818. }
  3819.  
  3820.     /* LocalCreateTask(STRPTR Name,BYTE Priority,TASKENTRY Entry,ULONG StackSize,LONG NumArgs,...):
  3821.      *
  3822.      *    Special version of CreateTask() that allows for arguments to be passed to
  3823.      *    the Task to be created.
  3824.      */
  3825.  
  3826. struct Task *
  3827. LocalCreateTask(STRPTR Name,LONG Priority,TASKENTRY Entry,ULONG StackSize,LONG NumArgs,...)
  3828. {
  3829.         /* A MemList with an additional MemEntry following it. */
  3830.  
  3831.     struct FatMemList
  3832.     {
  3833.         struct MemList    MemList;
  3834.         struct MemEntry    MemEntry;
  3835.     };
  3836.  
  3837.     struct MemList *LocalMemList,*MemList;
  3838.     struct FatMemList FatMemList;
  3839.     struct Task *Task;
  3840.  
  3841.         /* Limit the Task priority to legal values. */
  3842.  
  3843.     if(Priority < -128)
  3844.         Priority = -128;
  3845.     else
  3846.     {
  3847.         if(Priority > 127)
  3848.             Priority = 127;
  3849.     }
  3850.  
  3851.         /* Clear the result. */
  3852.  
  3853.     Task = NULL;
  3854.  
  3855.         /* Round the stack size to a multiple of four. */
  3856.  
  3857.     StackSize = (StackSize + 3) & ~3;
  3858.  
  3859.         /* Reset the contents of the local memory allocation request. */
  3860.  
  3861.     memset(&FatMemList,0,sizeof(FatMemList));
  3862.     LocalMemList = &FatMemList.MemList;
  3863.  
  3864.         /* Set up the memory allocation request; we want room for
  3865.          * the Task structure and the requested stack size plus
  3866.          * any arguments to pass to the new Task.
  3867.          */
  3868.  
  3869.     LocalMemList->ml_NumEntries            = 2;
  3870.     LocalMemList->ml_ME[0].me_Reqs        = MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR;
  3871.     LocalMemList->ml_ME[0].me_Length    = sizeof(struct Task);
  3872.     LocalMemList->ml_ME[1].me_Reqs        = MEMF_ANY|MEMF_CLEAR;
  3873.     LocalMemList->ml_ME[1].me_Length    = StackSize + NumArgs * sizeof(LONG);
  3874.  
  3875.         /* Try the allocation. */
  3876.  
  3877.     if(MemList = AllocEntry(LocalMemList))
  3878.     {
  3879.             /* Check if the allocation did work. */
  3880.  
  3881.         if((ULONG)MemList & 0x80000000)
  3882.         {
  3883.                 /* Strip the failure bit. */
  3884.  
  3885.             MemList = (struct MemList *)((ULONG)MemList & ~0x80000000);
  3886.         }
  3887.         else
  3888.         {
  3889.                 /* So we got the memory for the Task. */
  3890.  
  3891.             Task = (struct Task *)MemList->ml_ME[0].me_Addr;
  3892.  
  3893.                 /* Initialize the Task data structure. We will not
  3894.                  * copy the name to a separate buffer, it is assumed
  3895.                  * that the name pointer will remain valid for the
  3896.                  * entire life time of this Task.
  3897.                  */
  3898.  
  3899.             Task->tc_Node.ln_Pri    = Priority;
  3900.             Task->tc_Node.ln_Type    = NT_TASK;
  3901.             Task->tc_Node.ln_Name    = Name;
  3902.  
  3903.             Task->tc_SPLower        = MemList->ml_ME[1].me_Addr;
  3904.             Task->tc_SPUpper        = (APTR)((ULONG)Task->tc_SPLower + MemList->ml_ME[1].me_Length);
  3905.             Task->tc_SPReg            = (APTR)((ULONG)Task->tc_SPUpper - NumArgs * sizeof(LONG));
  3906.  
  3907.                 /* Add the memory to be released when the Task exits. */
  3908.  
  3909.             NewList(&Task->tc_MemEntry);
  3910.             AddTail(&Task->tc_MemEntry,(struct Node *)MemList);
  3911.  
  3912.                 /* If there are any arguments to pass to the Task,
  3913.                  * copy them onto the stack.
  3914.                  */
  3915.  
  3916.             if(NumArgs > 0)
  3917.             {
  3918.                 va_list VarArgs;
  3919.  
  3920.                 va_start(VarArgs,NumArgs);
  3921.                 CopyMem(VarArgs,Task->tc_SPReg,NumArgs * sizeof(LONG));
  3922.                 va_end(VarArgs);
  3923.             }
  3924.  
  3925.                 /* Try to launch the Task... */
  3926.  
  3927.             Task = AddTask(Task,(APTR)Entry,NULL);
  3928.         }
  3929.  
  3930.             /* Check if the Task could be launched and clean
  3931.              * up if it couldn't.
  3932.              */
  3933.  
  3934.         if(Task == NULL && MemList != NULL)
  3935.             FreeEntry(MemList);
  3936.     }
  3937.  
  3938.     return(Task);
  3939. }
  3940.  
  3941.     /* ChangeWindowPtr(APTR *Old,APTR New):
  3942.      *
  3943.      *    Change the pr_WindowPtr entry and return the old value.
  3944.      */
  3945.  
  3946. VOID
  3947. ChangeWindowPtr(APTR *Old,APTR New)
  3948. {
  3949.     struct Process *CurrentProcess;
  3950.  
  3951.     CurrentProcess = (struct Process *)FindTask(NULL);
  3952.  
  3953.     *Old = CurrentProcess->pr_WindowPtr;
  3954.  
  3955.     CurrentProcess->pr_WindowPtr = New;
  3956. }
  3957.  
  3958.     /* RestoreWindowPtr(APTR Old):
  3959.      *
  3960.      *    Restore the pr_WindowPtr to whatever it was poiting to.
  3961.      */
  3962.  
  3963. VOID
  3964. RestoreWindowPtr(APTR Old)
  3965. {
  3966.     ((struct Process *)FindTask(NULL))->pr_WindowPtr = Old;
  3967. }
  3968.  
  3969.     /* DisableDOSRequesters(APTR *WindowPtr):
  3970.      *
  3971.      *    Turn off the AmigaDOS requesters.
  3972.      */
  3973.  
  3974. VOID
  3975. DisableDOSRequesters(APTR *WindowPtr)
  3976. {
  3977.     ChangeWindowPtr(WindowPtr,(APTR)-1);
  3978. }
  3979.  
  3980.     /* EnableDOSRequesters(APTR WindowPtr):
  3981.      *
  3982.      *    Turn the AmigaDOS requesters back on.
  3983.      */
  3984.  
  3985. VOID
  3986. EnableDOSRequesters(APTR WindowPtr)
  3987. {
  3988.     RestoreWindowPtr(WindowPtr);
  3989. }
  3990.  
  3991.     /* SpeechSynthesizerAvailable():
  3992.      *
  3993.      *    Checks if the speech synthesizer is available for use.
  3994.      */
  3995.  
  3996. BOOL
  3997. SpeechSynthesizerAvailable()
  3998. {
  3999.     struct Library *LocalTranslatorBase;
  4000.     BOOL SpeechAvailable;
  4001.  
  4002.     SpeechAvailable = FALSE;
  4003.  
  4004.     if(LocalTranslatorBase = OpenLibrary("translator.library",0))
  4005.     {
  4006.         struct narrator_rb NarratorRequest;
  4007.  
  4008.         memset(&NarratorRequest,0,sizeof(NarratorRequest));
  4009.         NarratorRequest.message.io_Message.mn_Length = sizeof(NarratorRequest);
  4010.  
  4011.         if(!OpenDevice("narrator.device",0,(struct IORequest *)&NarratorRequest,NULL))
  4012.         {
  4013.             SpeechAvailable = TRUE;
  4014.  
  4015.             CloseDevice((struct IORequest *)&NarratorRequest);
  4016.         }
  4017.  
  4018.         CloseLibrary(LocalTranslatorBase);
  4019.     }
  4020.  
  4021.     return(SpeechAvailable);
  4022. }
  4023.  
  4024.     /* CurrentTimeToStamp(struct DateStamp *Stamp):
  4025.      *
  4026.      *    A replacement for DateStamp().
  4027.      */
  4028.  
  4029. VOID
  4030. CurrentTimeToStamp(struct DateStamp *Stamp)
  4031. {
  4032.     struct timeval Now;
  4033.  
  4034.     GetSysTime(&Now);
  4035.  
  4036.     Stamp->ds_Days        = Now.tv_secs / (24 * 60 * 60);
  4037.     Stamp->ds_Minute    = (Now.tv_secs % (24 * 60 * 60)) / 60;
  4038.     Stamp->ds_Tick        = (Now.tv_secs % 60) * TICKS_PER_SECOND + (TICKS_PER_SECOND * Now.tv_micro) / MILLION;
  4039. }
  4040.  
  4041.     /* SmartOpenDiskFont(struct TextAttr *TextAttr):
  4042.      *
  4043.      *    Opens a disk-resident font. Does not require diskfont.library
  4044.      *    to be open all the time while the program is running.
  4045.      */
  4046.  
  4047. struct TextFont *
  4048. SmartOpenDiskFont(struct TextAttr *TextAttr)
  4049. {
  4050.     struct TextFont *Result;
  4051.  
  4052.     Result = NULL;
  4053.  
  4054.     if(DiskfontBase = OpenLibrary("diskfont.library",0))
  4055.     {
  4056.         Result = OpenDiskFont(TextAttr);
  4057.  
  4058.         CloseLibrary(DiskfontBase);
  4059.     }
  4060.  
  4061.     if(!Result)
  4062.         Result = OpenFont(TextAttr);
  4063.  
  4064.     return(Result);
  4065. }
  4066.  
  4067.     /* ArmLimit(ULONG SecondsToGo):
  4068.      *
  4069.      *    Arm the limit counter. We remember the time when the limit
  4070.      *    will be exceeded.
  4071.      */
  4072.  
  4073. VOID
  4074. ArmLimit(ULONG SecondsToGo)
  4075. {
  4076.     GetSysTime(&LimitTime);
  4077.     LimitTime.tv_secs += SecondsToGo;
  4078. }
  4079.  
  4080.     /* DisarmLimit():
  4081.      *
  4082.      *    Clear the limit counter.
  4083.      */
  4084.  
  4085. VOID
  4086. DisarmLimit()
  4087. {
  4088.     memset(&LimitTime,0,sizeof(LimitTime));
  4089. }
  4090.  
  4091.     /* CheckLimit():
  4092.      *
  4093.      *    Check if the limit counter has been triggered.
  4094.      *    If triggered, clear the limit counter.
  4095.      */
  4096.  
  4097. BOOL
  4098. CheckLimit()
  4099. {
  4100.     BOOL Triggered;
  4101.  
  4102.     Triggered = FALSE;
  4103.  
  4104.     if(LimitTime.tv_secs > 0 || LimitTime.tv_micro > 0)
  4105.     {
  4106.         struct timeval Now;
  4107.  
  4108.         GetSysTime(&Now);
  4109.  
  4110.         if(-CmpTime(&Now,&LimitTime) >= 0)
  4111.             Triggered = TRUE;
  4112.     }
  4113.  
  4114.     if(Triggered)
  4115.         DisarmLimit();
  4116.  
  4117.     return(Triggered);
  4118. }
  4119.